Skip to content

Commit

Permalink
feat: Add unit Test for Navbar & Topbar Backend - Meeds-io/MIPs#159
Browse files Browse the repository at this point in the history
  • Loading branch information
boubaker committed Nov 26, 2024
1 parent efa73a6 commit bd4ab77
Show file tree
Hide file tree
Showing 25 changed files with 1,471 additions and 412 deletions.
2 changes: 1 addition & 1 deletion component/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<name>Meeds:: PLF:: Social Core Component</name>
<description>Meeds Social Core Component: People and Space</description>
<properties>
<exo.test.coverage.ratio>0.69</exo.test.coverage.ratio>
<exo.test.coverage.ratio>0.72</exo.test.coverage.ratio>
</properties>
<dependencies>
<!-- These dependency is required to compile but reported as useless by mvn dependency:analyze -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
/**
* This file is part of the Meeds project (https://meeds.io/).
*
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.meeds.social.navigation.plugin;

import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.stream.Stream;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.exoplatform.commons.utils.ExpressionUtil;
import org.exoplatform.portal.application.PortalRequestHandler;
import org.exoplatform.portal.config.UserACL;
import org.exoplatform.portal.config.model.Page;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.mop.PageType;
import org.exoplatform.portal.mop.SiteKey;
import org.exoplatform.portal.mop.SiteType;
import org.exoplatform.portal.mop.State;
import org.exoplatform.portal.mop.Visibility;
import org.exoplatform.portal.mop.navigation.NodeContext;
import org.exoplatform.portal.mop.navigation.NodeData;
import org.exoplatform.portal.mop.navigation.NodeState;
import org.exoplatform.portal.mop.service.DescriptionService;
import org.exoplatform.portal.mop.service.LayoutService;
import org.exoplatform.portal.mop.service.NavigationService;
import org.exoplatform.services.organization.Group;
import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.resources.LocaleConfigService;
import org.exoplatform.services.resources.LocaleContextInfo;
import org.exoplatform.services.resources.ResourceBundleManager;
import org.exoplatform.services.resources.ResourceBundleService;
import org.exoplatform.web.WebAppController;
import org.exoplatform.web.controller.QualifiedName;

import io.meeds.social.navigation.model.SidebarItem;
import io.meeds.social.translation.service.TranslationService;

import lombok.SneakyThrows;

public abstract class AbstractLayoutSidebarPlugin implements SidebarPlugin {

public static final String SITE_NAME_PROP_NAME = "siteName";

public static final String SITE_ID_PROP_NAME = "siteId";

public static final String SITE_TYPE_PROP_NAME = "siteType";

public static final String SITE_EXPAND_PAGES_PROP_NAME = "expandPages";

public static final String NODE_ID_PROP_NAME = "navigationNodeId";

public static final String SITE_DISPLAY_NAME_PROP_NAME = "siteDisplayName";

public static final String SITE_ICON_PROP_NAME = "siteIcon";

public static final String SITE_TRANSLATION_OBJECT_TYPE = "site";

public static final String SITE_TRANSLATION_LABEL_FIELD_NAME = "label";

@Autowired
protected NavigationService navigationService;

@Autowired
protected LayoutService layoutService;

@Autowired
protected TranslationService translationService;

@Autowired
protected DescriptionService descriptionService;

@Autowired
protected ResourceBundleManager resourceBundleManager;

@Autowired
protected LocaleConfigService localeConfigService;

@Autowired
protected OrganizationService organizationService;

@Autowired
protected UserACL userAcl;

@Autowired
private WebAppController webController;

protected SidebarItem resolvePageItemProperties(SidebarItem item, Locale locale) {
String nodeId = item.getProperties().get(NODE_ID_PROP_NAME);
NodeData node = navigationService.getNodeById(Long.parseLong(nodeId));

SiteKey siteKey = node.getSiteKey();
long siteId = getSiteId(siteKey);

item.setName(getNodeLabel(Long.parseLong(nodeId), locale));
item.setIcon(node.getState().getIcon());

item.setProperties(new HashMap<>(item.getProperties()));
item.getProperties().put(SITE_ID_PROP_NAME, String.valueOf(siteId));
item.getProperties().put(SITE_TYPE_PROP_NAME, siteKey.getTypeName());
item.getProperties().put(SITE_NAME_PROP_NAME, siteKey.getName());
item.getProperties().put(SITE_ICON_PROP_NAME, getSiteIcon(siteKey));
item.getProperties().put(SITE_DISPLAY_NAME_PROP_NAME, getSiteLabel(siteKey, locale));

Page page = layoutService.getPage(node.getState().getPageRef());
if (PageType.LINK.name().equals(page.getType())) {
item.setUrl(page.getLink());
item.setTarget(node.getState().getTarget());
} else {
item.setUrl(getNodeUri(node));
}
return item;
}

protected String getNodeLabel(long nodeId, Locale locale) {
NodeData nodeData = navigationService.getNodeById(nodeId);
Map<Locale, State> nodeLabels = descriptionService.getDescriptions(String.valueOf(nodeId));
if (MapUtils.isEmpty(nodeLabels)) {
return getLabelOrDefault(nodeData.getSiteKey(),
nodeData.getState().getLabel(),
locale,
StringUtils.firstNonBlank(nodeData.getState().getLabel(), nodeData.getName()));
} else if (nodeLabels.containsKey(locale)) {
return nodeLabels.get(locale).getName();
} else if (nodeLabels.containsKey(localeConfigService.getDefaultLocaleConfig().getLocale())) {
return nodeLabels.get(localeConfigService.getDefaultLocaleConfig().getLocale()).getName();
} else if (nodeLabels.containsKey(ResourceBundleService.DEFAULT_CROWDIN_LOCALE)) {
return nodeLabels.get(ResourceBundleService.DEFAULT_CROWDIN_LOCALE).getName();
} else {
return nodeLabels.values().iterator().next().getName();
}
}

protected String getSiteIcon(SiteKey siteKey) {
NodeContext<NodeContext<Object>> rootNode = navigationService.loadNode(siteKey);
if (rootNode != null && rootNode.getSize() > 0) {
Collection<NodeContext<Object>> nodes = rootNode.getNodes();
return nodes.stream().map(node -> {
NodeData data = node.getData();
NodeState state = data.getState();
if (isVisibilityEligible(state)
&& state.getPageRef() != null
&& StringUtils.isNotBlank(state.getIcon())) {
return state.getIcon();
} else {
return null;
}
}).filter(Objects::nonNull).findFirst().orElse(null);
}
return null;
}

@SneakyThrows
protected String getSiteLabel(SiteKey siteKey, Locale locale) {
long siteId = getSiteId(siteKey);
String label = translationService.getTranslationLabelOrDefault(SITE_TRANSLATION_OBJECT_TYPE,
siteId,
SITE_TRANSLATION_LABEL_FIELD_NAME,
locale);
if (StringUtils.isNotBlank(label)) {
return label;
}

PortalConfig site = layoutService.getPortalConfig(siteId);
label = StringUtils.firstNonBlank(site.getLabel(),
site.getName(),
siteKey.getName());
if (siteKey.getType() == SiteType.PORTAL) {
return getLabelOrDefault(siteKey, label, locale, siteKey.getName());
} else if (siteKey.getType() == SiteType.GROUP) {
Group siteGroup = organizationService.getGroupHandler()
.findGroupById(siteKey.getName());
if (siteGroup != null) {
return siteGroup.getLabel();
}
}
return label;
}

protected boolean isEligiblePage(long nodeId, String username) {
NodeData node = navigationService.getNodeById(nodeId);
if (node == null || node.getSiteKey() == null || node.getState() == null) {
return false;
} else {
PortalConfig site = layoutService.getPortalConfig(node.getSiteKey());
if (!userAcl.hasAccessPermission(site, userAcl.getUserIdentity(username))) {
return false;
} else if (node.getState() == null
|| !isVisibilityEligible(node.getState())) {
return false;
} else if (node.getState().getPageRef() == null) {
return node.iterator(false).hasNext();
} else {
Page page = layoutService.getPage(node.getState().getPageRef());
if (page == null) {
return node.iterator(false).hasNext();
} else {
return userAcl.hasAccessPermission(page, userAcl.getUserIdentity(username));
}
}
}
}

protected boolean isVisibilityEligible(NodeState state) {
if (state.getVisibility() == Visibility.DISPLAYED) {
return true;
} else if (state.getVisibility() == Visibility.TEMPORAL) {
return (state.getEndPublicationTime() == 0 || state.getEndPublicationTime() < System.currentTimeMillis())
&& (state.getStartPublicationTime() == 0 || state.getStartPublicationTime() > System.currentTimeMillis());
}
return false;
}

private String getNodeUri(NodeData node) {
SiteKey siteKey = node.getSiteKey();
StringBuilder uriBuilder = new StringBuilder();
buildUri(node, uriBuilder);

Map<QualifiedName, String> params = new HashMap<>();
params.put(WebAppController.HANDLER_PARAM, PortalRequestHandler.HANDLER_NAME);
params.put(PortalRequestHandler.REQUEST_SITE_NAME, siteKey.getName());
params.put(PortalRequestHandler.REQUEST_SITE_TYPE, siteKey.getTypeName());
params.put(PortalRequestHandler.REQUEST_PATH, uriBuilder.toString().replaceFirst("/", ""));
params.put(PortalRequestHandler.LANG, Locale.ENGLISH.toLanguageTag());
return "/portal" +
webController.getRouter().render(params).replace("/en", "").replace("?lang=en", "").replace("&lang=en", "");
}

private void buildUri(NodeData node, StringBuilder uriBuilder) {
if (StringUtils.isNotBlank(node.getName())
&& !StringUtils.equals(node.getName(), "default")) {
uriBuilder.insert(0, node.getName());
if (!uriBuilder.isEmpty()) {
uriBuilder.insert(0, "/");
}
}
if (StringUtils.isNotBlank(node.getParentId())) {
NodeData parentNode = navigationService.getNodeById(Long.parseLong(node.getParentId()));
buildUri(parentNode, uriBuilder);
}
}

private String getLabelOrDefault(SiteKey siteKey, String label, Locale locale, String defaultLabel) {
if (ExpressionUtil.isResourceBindingExpression(label)) {
return Stream.of(locale, ResourceBundleService.DEFAULT_CROWDIN_LOCALE)
.map(l -> getBundle(siteKey.getTypeName(), siteKey.getName(), locale))
.filter(Objects::nonNull)
.map(b -> ExpressionUtil.getExpressionValue(b, label))
.filter(StringUtils::isNotBlank)
.findFirst()
.orElse(defaultLabel);
} else {
return StringUtils.firstNonBlank(label, defaultLabel);
}
}

private long getSiteId(SiteKey siteKey) {
PortalConfig site = layoutService.getPortalConfig(siteKey);
return Long.parseLong((site.getStorageId().split("_"))[1]);
}

private ResourceBundle getBundle(String siteType, String siteName, Locale locale) {
return resourceBundleManager.getNavigationResourceBundle(LocaleContextInfo.getLocaleAsString(locale),
siteType,
siteName);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -58,7 +59,10 @@ protected List<SidebarItem> getSpaces(SidebarItem item, String username) {
buildSpaceFilter(item, spaceFilter);
int limit = getLimit(item);
Space[] spaces = getSpaces(item, spaceFilter, username, sortBy, limit);
return Arrays.stream(spaces).map(this::toSidebarItem).toList();
return Arrays.stream(spaces)
.filter(Objects::nonNull)
.map(this::toSidebarItem)
.toList();
}

protected SidebarItem toSidebarItem(Space space) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
*/
package io.meeds.social.navigation.plugin;

import static io.meeds.social.navigation.plugin.SidebarPluginUtils.getNameFromProperties;

import java.util.Collections;
import java.util.List;
import java.util.Locale;

import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
Expand All @@ -37,7 +37,7 @@
@Order(50)
public class LinkSidebarPlugin implements SidebarPlugin {

public static final String LINK_NAMES = "names";
public static final String LINK_NAMES = "names";

@Autowired
private LocaleConfigService localeConfigService;
Expand All @@ -49,19 +49,7 @@ public SidebarItemType getType() {

@Override
public SidebarItem resolveProperties(SidebarItem item, String username, Locale locale) {
String names = item.getProperties().get(LINK_NAMES);
JSONObject jsonObject = new JSONObject(names);
String lang = getLang(locale);
Object name = getName(jsonObject, lang);
if (name == null) {
lang = getLang(localeConfigService.getDefaultLocaleConfig().getLocale());
name = getName(jsonObject, lang);
if (name == null) {
lang = jsonObject.keys().next();
name = getName(jsonObject, lang);
}
}
item.setName(String.valueOf(name));
item.setName(getNameFromProperties(localeConfigService, item, LINK_NAMES, locale));
return item;
}

Expand All @@ -75,16 +63,4 @@ public boolean itemExists(SidebarItem item, String username) {
return true;
}

private String getLang(Locale locale) {
return locale.toLanguageTag().replace("-", "_");
}

private Object getName(JSONObject jsonObject, String lang) {
try {
return jsonObject.get(lang);
} catch (JSONException e) {
return null;
}
}

}
Loading

0 comments on commit bd4ab77

Please sign in to comment.