From d8926085ad4a2f940cc6dc932e961746423cdd9b Mon Sep 17 00:00:00 2001 From: Krisztina Elekes Date: Thu, 3 Oct 2024 13:23:02 +0300 Subject: [PATCH] fix: always skip exclude_from_nav items in navigation, regardless of context path - refs #269983 (#168) --- eea/climateadapt/restapi/navigation.py | 93 +++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/eea/climateadapt/restapi/navigation.py b/eea/climateadapt/restapi/navigation.py index 19c84b7ec..affecca13 100644 --- a/eea/climateadapt/restapi/navigation.py +++ b/eea/climateadapt/restapi/navigation.py @@ -1,17 +1,22 @@ from Acquisition import aq_inner +from collections import defaultdict from plone.memoize.view import memoize +from plone.registry.interfaces import IRegistry from plone.restapi.interfaces import IExpandableElement, IPloneRestapiLayer from plone.restapi.services.navigation.get import Navigation as BaseNavigation from plone.restapi.services.navigation.get import \ NavigationGet as BaseNavigationGet +from plone.restapi.serializer.converters import json_compatible from Products.CMFCore.utils import getToolByName from Products.CMFPlone import utils +from Products.CMFPlone.utils import safe_unicode from Products.CMFPlone.browser.navigation import \ CatalogNavigationTabs as BaseCatalogNavigationTabs from Products.CMFPlone.browser.navigation import get_id, get_view_url from urlparse import urlparse -from zope.component import adapter, getMultiAdapter +from zope.component import adapter, getMultiAdapter, getUtility from zope.interface import Interface, implementer +from zope.i18n import translate # if '/mission' not in self.context.absolute_url(relative=True): @@ -123,6 +128,92 @@ def __call__(self, expand=False): result["navigation"]["items"] = self.build_tree(self.navtree_path) return result + @property + @memoize + def navtree(self): + ret = defaultdict(list) + navtree_path = self.navtree_path + for tab in self.portal_tabs: + entry = {} + entry.update( + { + "path": "/".join((navtree_path, tab["id"])), + "description": tab["description"], + "@id": tab["url"], + } + ) + if "review_state" in tab: + entry["review_state"] = json_compatible(tab["review_state"]) + else: + entry["review_state"] = None + + if "title" not in entry: + entry["title"] = tab.get("name") or tab.get("description") or tab["id"] + else: + # translate Home tab + entry["title"] = translate( + entry["title"], domain="plone", context=self.request + ) + + entry["title"] = safe_unicode(entry["title"]) + ret[navtree_path].append(entry) + + query = { + "path": { + "query": self.navtree_path, + "depth": self.depth, + }, + "portal_type": {"query": self.settings["displayed_types"]}, + "Language": self.current_language, + "is_default_page": False, + "sort_on": "getObjPositionInParent", + } + + if not self.settings["nonfolderish_tabs"]: + query["is_folderish"] = True + + if self.settings["filter_on_workflow"]: + query["review_state"] = list(self.settings["workflow_states_to_show"] or ()) + + if not self.settings["show_excluded_items"]: + query["exclude_from_nav"] = False + + context_path = "/".join(self.context.getPhysicalPath()) + portal_catalog = getToolByName(self.context, "portal_catalog") + brains = portal_catalog.searchResults(**query) + + registry = getUtility(IRegistry) + types_using_view = registry.get("plone.types_use_view_action_in_listings", []) + + for brain in brains: + brain_path = brain.getPath() + brain_parent_path = brain_path.rpartition("/")[0] + if brain_parent_path == navtree_path: + # This should be already provided by the portal_tabs_view + continue + # Customization: + # Remove `and not context_path.startswith(brain_path)` from the condition + # to ensure we skip items marked as excluded (exclude_from_nav) even + # if they are in the current context path. + if brain.exclude_from_nav: + continue + url = brain.getURL() + entry = { + "path": brain_path, + "@id": url, + "title": safe_unicode(brain.Title), + "description": safe_unicode(brain.Description), + "review_state": json_compatible(brain.review_state), + "use_view_action_in_listings": brain.portal_type in types_using_view, + } + + if brain.get("nav_title", False): + entry.update({"title": brain["nav_title"]}) + + self.customize_entry(entry, brain) + ret[brain_parent_path].append(entry) + return ret + def customize_entry(self, entry, brain): entry["brain"] = brain