From e6b6b1087ec7bcc11d4238efc89a5562f44800e6 Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Thu, 23 Nov 2023 17:33:06 +0100 Subject: [PATCH] Honor types not searched in search filters (#58) * Do not return section children in @search-filters endpoint if they are types omitted from search results * Do not return section children in @search-filters endpoint if they are types omitted from search results * better handle empty value Co-authored-by: Mauro Amico --------- Co-authored-by: Mauro Amico --- CHANGES.rst | 3 +- .../policy/restapi/search_filters/get.py | 74 +++++++++---------- .../policy/tests/test_search_filters_api.py | 29 ++++++++ 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 3e9c243..126b0c5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,8 @@ Changelog 5.0.7 (unreleased) ------------------ -- Nothing changed yet. +- Do not return section children in @search-filters endpoint if they are types omitted from search results. + [cekk] 5.0.6 (2023-08-29) diff --git a/src/design/plone/policy/restapi/search_filters/get.py b/src/design/plone/policy/restapi/search_filters/get.py index d4185ab..6b8f0d8 100644 --- a/src/design/plone/policy/restapi/search_filters/get.py +++ b/src/design/plone/policy/restapi/search_filters/get.py @@ -6,6 +6,7 @@ from plone.restapi.interfaces import ISerializeToJsonSummary from plone.restapi.services import Service from Products.CMFPlone.interfaces import ISearchSchema +from Products.CMFCore.utils import getToolByName from zope.component import getMultiAdapter from zope.component import getUtility from zope.i18n import translate @@ -38,46 +39,45 @@ def get_portal_types(self): def reply(self): settings = api.portal.get_registry_record( - "search_sections", - interface=IDesignPloneSettings, + "search_sections", interface=IDesignPloneSettings, default="[]" ) + utils = getToolByName(self.context, "plone_utils") + sections = [] - if settings: - settings = json.loads(settings) - for setting in settings: - items = [] - for section_settings in setting.get("items") or []: - for uid in section_settings.get("linkUrl") or []: - try: - section = api.content.get(UID=uid) - except Unauthorized: - # private folder - continue - if section: - item_infos = getMultiAdapter( - (section, self.request), - ISerializeToJsonSummary, - )() - children = section.listFolderContents() - if children: - item_infos["items"] = [] - for children in section.listFolderContents(): - item_infos["items"].append( - getMultiAdapter( - (children, self.request), - ISerializeToJsonSummary, - )() - ) - if section_settings.get("title", ""): - item_infos["title"] = section_settings["title"] - items.append(item_infos) - if items: - sections.append( - { - "rootPath": setting.get("rootPath", ""), - "items": items, - } + for setting in json.loads(settings or "[]"): + items = [] + for section_settings in setting.get("items") or []: + for uid in section_settings.get("linkUrl") or []: + try: + section = api.content.get(UID=uid) + except Unauthorized: + # private folder + continue + if not section: + continue + item_infos = getMultiAdapter( + (section, self.request), + ISerializeToJsonSummary, + )() + children = section.listFolderContents( + contentFilter={"portal_type": utils.getUserFriendlyTypes()} ) + item_infos["items"] = [ + getMultiAdapter( + (x, self.request), + ISerializeToJsonSummary, + )() + for x in children + ] + item_infos["title"] = section_settings.get("title", "") + items.append(item_infos) + if items: + sections.append( + { + "rootPath": setting.get("rootPath", ""), + "items": items, + } + ) topics = [ getMultiAdapter( (brain, self.request), diff --git a/src/design/plone/policy/tests/test_search_filters_api.py b/src/design/plone/policy/tests/test_search_filters_api.py index 11084ad..6cc4b67 100644 --- a/src/design/plone/policy/tests/test_search_filters_api.py +++ b/src/design/plone/policy/tests/test_search_filters_api.py @@ -97,3 +97,32 @@ def test_endpoint_return_list_of_searchable_types(self): self.assertIn("portal_types", response) types = [x["id"] for x in response["portal_types"]] self.assertNotIn("Document", types) + + def test_endpoint_do_not_return_contents_that_are_not_searchable(self): + api.content.create( + container=self.portal["amministrazione"], + type="UnitaOrganizzativa", + title="UO Foo", + id="uo-foo", + ) + commit() + + response = self.api_session.get("/@search-filters").json() + amministrazione = response["sections"][0]["items"][0] + + self.assertEqual("Amministrazione", amministrazione["title"]) + self.assertEqual(8, len(amministrazione["items"])) + self.assertEqual("UO Foo", amministrazione["items"][-1]["title"]) + + registry = getUtility(IRegistry) + settings = registry.forInterface(ISearchSchema, prefix="plone") + settings.types_not_searched = tuple( + list(settings.types_not_searched) + ["UnitaOrganizzativa"] + ) + commit() + + response = self.api_session.get("/@search-filters").json() + amministrazione = response["sections"][0]["items"][0] + + self.assertEqual("Amministrazione", amministrazione["title"]) + self.assertEqual(7, len(amministrazione["items"]))