From 1d0e64e0a0506e79d2813eb7b59756213341ff4a Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Wed, 28 May 2025 14:25:44 +0200 Subject: [PATCH 1/7] Handle sort_on also when using AdvancedQuery. --- CHANGES.rst | 3 ++- .../volto/restapi/services/search/get.py | 20 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 024fbade..3d598941 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,7 +6,8 @@ Changelog - Fix rss feed image selection, now it uses the correct field for preview_image. [mamico] - +- Handle sort_on also when using AdvancedQuery. + [cekk] 5.5.10 (2025-05-09) ------------------- diff --git a/src/redturtle/volto/restapi/services/search/get.py b/src/redturtle/volto/restapi/services/search/get.py index 5ba222f7..e12fb986 100644 --- a/src/redturtle/volto/restapi/services/search/get.py +++ b/src/redturtle/volto/restapi/services/search/get.py @@ -44,8 +44,6 @@ def get_indexes_mapping(self): def is_advanced_query(self, query): if not query: return False - if query.get("sort_on", None): - return False if query.get("SimpleQuery", None): return False custom_ranking_enabled = api.portal.get_registry_record( @@ -76,11 +74,19 @@ def search(self, query=None): # TODO: mettere i parametri di ranking in registry # XXX: il default sul subject ha senso ? (probabilmente no), rivedere eventualmente anche i test term = query.get("SearchableText") - rs = RankByQueries_Sum( - (Eq("Subject", term), 16), - (Eq("Title", term), 8), - (Eq("Description", term), 6), - ) + + if "sort_on" in query: + sort_order = query.get("sort_order", "asc") + if sort_order == "reverse": + sort_order = "desc" + rs = (query["sort_on"], sort_order) + else: + # use custom ranking + rs = RankByQueries_Sum( + (Eq("Subject", term), 16), + (Eq("Title", term), 8), + (Eq("Description", term), 6), + ) lazy_resultset = self.catalog.evalAdvancedQuery( # Eq("SearchableText", term), (rs,), **query And(*queries), From 1a62bb6c7ff93230fac62533768d3dd63313a164 Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Wed, 28 May 2025 16:57:02 +0200 Subject: [PATCH 2/7] remove jbot dependency and fix tests --- CHANGES.rst | 4 +++ buildout.cfg | 2 ++ setup.py | 1 - src/redturtle/volto/__init__.py | 8 +++-- src/redturtle/volto/browser/configure.zcml | 34 ++++++++++++++----- .../RSS.pt} | 1 - .../document.pt} | 0 .../voltobackendwarning.pt} | 1 - src/redturtle/volto/interfaces.py | 4 +-- .../volto/restapi/services/search/get.py | 5 +++ .../volto/tests/test_advancedsearch.py | 34 ++++++++++++++++--- test_plone60.cfg | 15 -------- 12 files changed, 73 insertions(+), 36 deletions(-) rename src/redturtle/volto/browser/{overrides/Products.CMFPlone.browser.syndication.templates.RSS.pt => templates/RSS.pt} (99%) rename src/redturtle/volto/browser/{overrides/plone.app.contenttypes.browser.templates.document.pt => templates/document.pt} (100%) rename src/redturtle/volto/browser/{overrides/plone.volto.browser.voltobackendwarning.pt => templates/voltobackendwarning.pt} (97%) diff --git a/CHANGES.rst b/CHANGES.rst index 3d598941..1ae55d91 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,10 @@ Changelog [mamico] - Handle sort_on also when using AdvancedQuery. [cekk] +- Remove z3c.jbot compatibility and customize templates in standard-way. + [cekk] +- Force indexing subjects in SearchableText with ICategorization to keep the old Plone functionality (remove this when the official pr is merged). + [cekk] 5.5.10 (2025-05-09) ------------------- diff --git a/buildout.cfg b/buildout.cfg index 9f275f17..09552335 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -4,4 +4,6 @@ extends = test_plone60.cfg +eggs-directory = eggs + [versions] diff --git a/setup.py b/setup.py index 808846c9..8035362f 100644 --- a/setup.py +++ b/setup.py @@ -62,7 +62,6 @@ "plone.restapi>=9.6.0", "Products.PortalTransforms>=3.2.0", "collective.volto.sitesettings", - "z3c.jbot", ], extras_require={ "advancedquery": [ diff --git a/src/redturtle/volto/__init__.py b/src/redturtle/volto/__init__.py index 86397e01..8289008e 100644 --- a/src/redturtle/volto/__init__.py +++ b/src/redturtle/volto/__init__.py @@ -7,15 +7,19 @@ from zope.i18nmessageid import MessageFactory from ZTUtils.Lazy import LazyCat from ZTUtils.Lazy import LazyMap +from plone.app.dexterity.textindexer import utils +from plone.app.dexterity.behaviors.metadata import ICategorization + import logging logger = logging.getLogger(__name__) - - _ = MessageFactory("redturtle.volto") +# Index also subjects in SearchableText. +utils.searchable(ICategorization, "subjects") + PERMISSIONS["plone.app.vocabularies.Keywords"] = "View" # CATALOG PATCHES diff --git a/src/redturtle/volto/browser/configure.zcml b/src/redturtle/volto/browser/configure.zcml index 126261bf..8b294b73 100644 --- a/src/redturtle/volto/browser/configure.zcml +++ b/src/redturtle/volto/browser/configure.zcml @@ -5,15 +5,6 @@ i18n_domain="redturtle.volto" > - - - + + + - diff --git a/src/redturtle/volto/browser/overrides/plone.app.contenttypes.browser.templates.document.pt b/src/redturtle/volto/browser/templates/document.pt similarity index 100% rename from src/redturtle/volto/browser/overrides/plone.app.contenttypes.browser.templates.document.pt rename to src/redturtle/volto/browser/templates/document.pt diff --git a/src/redturtle/volto/browser/overrides/plone.volto.browser.voltobackendwarning.pt b/src/redturtle/volto/browser/templates/voltobackendwarning.pt similarity index 97% rename from src/redturtle/volto/browser/overrides/plone.volto.browser.voltobackendwarning.pt rename to src/redturtle/volto/browser/templates/voltobackendwarning.pt index fc3462ed..ead63e9e 100644 --- a/src/redturtle/volto/browser/overrides/plone.volto.browser.voltobackendwarning.pt +++ b/src/redturtle/volto/browser/templates/voltobackendwarning.pt @@ -1,3 +1,2 @@ - diff --git a/src/redturtle/volto/interfaces.py b/src/redturtle/volto/interfaces.py index 54d377f1..ee048649 100644 --- a/src/redturtle/volto/interfaces.py +++ b/src/redturtle/volto/interfaces.py @@ -1,16 +1,16 @@ # -*- coding: utf-8 -*- -# from zope.publisher.interfaces.browser import IDefaultBrowserLayer from plone.app.contenttypes.interfaces import ( IPloneAppContenttypesLayer as IDefaultBrowserLayer, ) from plone.dexterity.interfaces import IDexterityContent from plone.restapi.controlpanels.interfaces import IControlpanel +from plone.volto.interfaces import IPloneVoltoCoreLayer from redturtle.volto import _ from zope.interface import Interface from zope.schema import Bool -class IRedturtleVoltoLayer(IDefaultBrowserLayer): +class IRedturtleVoltoLayer(IDefaultBrowserLayer, IPloneVoltoCoreLayer): """Marker interface that defines a browser layer.""" diff --git a/src/redturtle/volto/restapi/services/search/get.py b/src/redturtle/volto/restapi/services/search/get.py index e12fb986..402253e2 100644 --- a/src/redturtle/volto/restapi/services/search/get.py +++ b/src/redturtle/volto/restapi/services/search/get.py @@ -75,6 +75,11 @@ def search(self, query=None): # XXX: il default sul subject ha senso ? (probabilmente no), rivedere eventualmente anche i test term = query.get("SearchableText") + rs = RankByQueries_Sum( + (Eq("Subject", term), 16), + (Eq("Title", term), 8), + (Eq("Description", term), 6), + ) if "sort_on" in query: sort_order = query.get("sort_order", "asc") if sort_order == "reverse": diff --git a/src/redturtle/volto/tests/test_advancedsearch.py b/src/redturtle/volto/tests/test_advancedsearch.py index abf58c55..5b0268f3 100644 --- a/src/redturtle/volto/tests/test_advancedsearch.py +++ b/src/redturtle/volto/tests/test_advancedsearch.py @@ -41,7 +41,7 @@ def setUp(self): type="Document", id="d1", title="document", - description="Foo document", + description="Document with subject", subject=["foo", "bar"], ) # 3rd for "Foo" (title + searchableText) @@ -84,7 +84,7 @@ def test_simplesearch(self): self.assertEqual(result["items_total"], 3) # explain why the order is different from the one in the test above self.assertEqual( - ["f1", "d1", "e1"], [item["@id"].split("/")[-1] for item in result["items"]] + ["f1", "e1", "d1"], [item["@id"].split("/")[-1] for item in result["items"]] ) def test_search_foo(self): @@ -163,7 +163,7 @@ def test_search_by_not_handled_index_type_return_standard_order(self): result = response.json() self.assertEqual(result["items_total"], 3) self.assertEqual( - ["f1", "d1", "e1"], [item["@id"].split("/")[-1] for item in result["items"]] + ["f1", "e1", "d1"], [item["@id"].split("/")[-1] for item in result["items"]] ) def test_search_no_query(self): @@ -195,7 +195,31 @@ def test_search_ignore_non_existent_indexes_and_return_custom_order_if_possible( result = response.json() self.assertEqual(result["items_total"], 3) self.assertEqual( - ["f1", "d1", "e1"], [item["@id"].split("/")[-1] for item in result["items"]] + ["f1", "e1", "d1"], [item["@id"].split("/")[-1] for item in result["items"]] + ) + + def test_search_use_sort_on_if_in_query_and_ignore_custom_order( + self, + ): + response = self.api_session.get( + "/@search", params={"SearchableText": "foo", "sort_on": "sortable_title"} + ) + result = response.json() + self.assertEqual(result["items_total"], 3) + self.assertEqual( + ["d1", "e1", "f1"], + [item["@id"].split("/")[-1] for item in result["items"]], + ) + + # now repeat query with no sort_on and have custom order + response = self.api_session.get( + "/@search", + params={"SearchableText": "foo"}, + ) + result = response.json() + self.assertEqual(result["items_total"], 3) + self.assertEqual( + ["d1", "f1", "e1"], [item["@id"].split("/")[-1] for item in result["items"]] ) @@ -207,7 +231,7 @@ def test_by_default_flag_is_disabled(self): self.assertEqual(result["items_total"], 3) # explain why the order is different from the one in the test above self.assertEqual( - ["f1", "d1", "e1"], [item["@id"].split("/")[-1] for item in result["items"]] + ["f1", "e1", "d1"], [item["@id"].split("/")[-1] for item in result["items"]] ) def test_enabling_flag_return_custom_order(self): diff --git a/test_plone60.cfg b/test_plone60.cfg index c0e79122..3c739e00 100644 --- a/test_plone60.cfg +++ b/test_plone60.cfg @@ -6,18 +6,3 @@ extends = base.cfg [versions] -docutils = - -# Added by buildout at 2023-03-10 11:55:21.122842 -Products.AdvancedQuery = 4.2.1 -createcoverage = 1.5 -dm.plone.advancedquery = 1.0 -flake8 = 6.0.0 -mccabe = 0.7.0 -plone.recipe.codeanalysis = 3.0.1 -pycodestyle = 2.10.0 -pyflakes = 3.0.1 -docutils = 0.21.2 -plone.stringinterp = 2.0.0 -# plone.restapi >= 9.6.1 don't put subjects into SearchableText (to investigate) -plone.restapi = 9.6.0 From 8ba6fe87a6f4eec1d87e494df477f7dd576a4d32 Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Wed, 28 May 2025 16:58:32 +0200 Subject: [PATCH 3/7] isort --- src/redturtle/volto/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/redturtle/volto/__init__.py b/src/redturtle/volto/__init__.py index 8289008e..ae368d9f 100644 --- a/src/redturtle/volto/__init__.py +++ b/src/redturtle/volto/__init__.py @@ -1,15 +1,14 @@ # -*- coding: utf-8 -*- """Init and utils.""" from plone.app.content.browser.vocabulary import PERMISSIONS +from plone.app.dexterity.behaviors.metadata import ICategorization +from plone.app.dexterity.textindexer import utils from plone.folder.nogopip import GopipIndex from Products.ZCatalog.Catalog import Catalog from redturtle.volto.catalogplan import Catalog_sorted_search_indexes from zope.i18nmessageid import MessageFactory from ZTUtils.Lazy import LazyCat from ZTUtils.Lazy import LazyMap -from plone.app.dexterity.textindexer import utils -from plone.app.dexterity.behaviors.metadata import ICategorization - import logging From 8699eb8e335a9171c343e1d3836d8e0262cbdd43 Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Wed, 28 May 2025 17:15:06 +0200 Subject: [PATCH 4/7] remove tmp config --- buildout.cfg | 2 -- src/redturtle/volto/restapi/services/search/get.py | 5 ----- 2 files changed, 7 deletions(-) diff --git a/buildout.cfg b/buildout.cfg index 09552335..9f275f17 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -4,6 +4,4 @@ extends = test_plone60.cfg -eggs-directory = eggs - [versions] diff --git a/src/redturtle/volto/restapi/services/search/get.py b/src/redturtle/volto/restapi/services/search/get.py index 402253e2..e12fb986 100644 --- a/src/redturtle/volto/restapi/services/search/get.py +++ b/src/redturtle/volto/restapi/services/search/get.py @@ -75,11 +75,6 @@ def search(self, query=None): # XXX: il default sul subject ha senso ? (probabilmente no), rivedere eventualmente anche i test term = query.get("SearchableText") - rs = RankByQueries_Sum( - (Eq("Subject", term), 16), - (Eq("Title", term), 8), - (Eq("Description", term), 6), - ) if "sort_on" in query: sort_order = query.get("sort_order", "asc") if sort_order == "reverse": From 09269f39ca47cb83817ee59bf48862a4a37a64a6 Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Thu, 29 May 2025 10:51:11 +0200 Subject: [PATCH 5/7] fix default --- src/redturtle/volto/restapi/services/search/get.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redturtle/volto/restapi/services/search/get.py b/src/redturtle/volto/restapi/services/search/get.py index e12fb986..3bbe8fc3 100644 --- a/src/redturtle/volto/restapi/services/search/get.py +++ b/src/redturtle/volto/restapi/services/search/get.py @@ -78,7 +78,7 @@ def search(self, query=None): if "sort_on" in query: sort_order = query.get("sort_order", "asc") if sort_order == "reverse": - sort_order = "desc" + sort_order = "asc" rs = (query["sort_on"], sort_order) else: # use custom ranking From 6932dcd78de8d6fcd3663ab6b37d079a01996dd6 Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Thu, 29 May 2025 10:56:14 +0200 Subject: [PATCH 6/7] fix default --- src/redturtle/volto/restapi/services/search/get.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redturtle/volto/restapi/services/search/get.py b/src/redturtle/volto/restapi/services/search/get.py index 3bbe8fc3..e12fb986 100644 --- a/src/redturtle/volto/restapi/services/search/get.py +++ b/src/redturtle/volto/restapi/services/search/get.py @@ -78,7 +78,7 @@ def search(self, query=None): if "sort_on" in query: sort_order = query.get("sort_order", "asc") if sort_order == "reverse": - sort_order = "asc" + sort_order = "desc" rs = (query["sort_on"], sort_order) else: # use custom ranking From 946f967654e13c7ff60b251b0bb54279939cb7dc Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Thu, 29 May 2025 11:55:27 +0200 Subject: [PATCH 7/7] fix sort_order logic --- src/redturtle/volto/restapi/services/search/get.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/redturtle/volto/restapi/services/search/get.py b/src/redturtle/volto/restapi/services/search/get.py index e12fb986..f0b27223 100644 --- a/src/redturtle/volto/restapi/services/search/get.py +++ b/src/redturtle/volto/restapi/services/search/get.py @@ -75,8 +75,14 @@ def search(self, query=None): # XXX: il default sul subject ha senso ? (probabilmente no), rivedere eventualmente anche i test term = query.get("SearchableText") - if "sort_on" in query: - sort_order = query.get("sort_order", "asc") + sort_on = query.get("sort_on", "") + if sort_on: + sort_order = query.get("sort_order", "") + if not sort_order: + if sort_on in ["Date", "effective"]: + sort_order = "desc" + else: + sort_order = "asc" if sort_order == "reverse": sort_order = "desc" rs = (query["sort_on"], sort_order)