diff --git a/CHANGES.rst b/CHANGES.rst index 8ddae443..127634f7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,9 +4,13 @@ Changelog 5.2.1 (unreleased) ------------------ +- Use plone.volto uid_to_url method to convert resolveuid links in summary. + [cekk] +- Patch plone.restapi RESOLVEUID_RE regexp to catch more urls. + [cekk] - Ignore non-existing indexes in custom ranking. [cekk] - + 5.2.0 (2023-08-21) ------------------ diff --git a/src/redturtle/volto/__init__.py b/src/redturtle/volto/__init__.py index be7550d8..a6c1363b 100644 --- a/src/redturtle/volto/__init__.py +++ b/src/redturtle/volto/__init__.py @@ -7,10 +7,10 @@ from zope.i18nmessageid import MessageFactory from ZTUtils.Lazy import LazyCat from ZTUtils.Lazy import LazyMap - +from plone.restapi.serializer import utils import logging - +import re logger = logging.getLogger(__name__) @@ -76,3 +76,6 @@ def Catalog_sortResults( logger.info("install monkey patch for Products.ZCatalog.Catalog.Catalog.sortResults") Catalog._orig_sortResults = Catalog.sortResults Catalog.sortResults = Catalog_sortResults + +# patch plone.restapi regexp to catch also other +utils.RESOLVEUID_RE = re.compile(".*?/resolve[Uu]id/([^/]*)/?(.*)$") diff --git a/src/redturtle/volto/restapi/serializer/dxfields.py b/src/redturtle/volto/restapi/serializer/dxfields.py index 2eb9f939..2d623186 100644 --- a/src/redturtle/volto/restapi/serializer/dxfields.py +++ b/src/redturtle/volto/restapi/serializer/dxfields.py @@ -3,17 +3,17 @@ from plone.app.contenttypes.utils import replace_link_variables_by_paths from plone.app.dexterity.behaviors.metadata import IPublication from plone.dexterity.interfaces import IDexterityContent -from plone.outputfilters.browser.resolveuid import uuidToURL from plone.restapi.interfaces import IFieldSerializer from plone.restapi.serializer.converters import json_compatible from plone.restapi.serializer.dxfields import DefaultFieldSerializer +from plone.restapi.serializer.utils import uid_to_url from redturtle.volto.interfaces import IRedturtleVoltoLayer from zope.component import adapter -from zope.component import getMultiAdapter from zope.interface import implementer from zope.schema.interfaces import IDatetime from zope.schema.interfaces import ITextLine + import re @@ -26,21 +26,10 @@ def __call__(self): if self.field.getName() != "remoteUrl": return super(TextLineFieldSerializer, self).__call__() value = self.get_value() - path = replace_link_variables_by_paths(context=self.context, url=value) - match = RESOLVEUID_RE.match(path) - if match: - uid, suffix = match.groups() - value = uuidToURL(uid) - else: - portal = getMultiAdapter( - (self.context, self.context.REQUEST), name="plone_portal_state" - ).portal() - ref_obj = portal.restrictedTraverse(path, None) - if ref_obj: - value = ref_obj.absolute_url() + url = uid_to_url(path) - return json_compatible(value) + return json_compatible(url) @adapter(IDatetime, IDexterityContent, IRedturtleVoltoLayer) diff --git a/src/redturtle/volto/restapi/serializer/summary.py b/src/redturtle/volto/restapi/serializer/summary.py index fcffe63e..f1b49bb8 100644 --- a/src/redturtle/volto/restapi/serializer/summary.py +++ b/src/redturtle/volto/restapi/serializer/summary.py @@ -2,22 +2,18 @@ from plone import api from plone.app.contenttypes.interfaces import ILink from plone.app.contenttypes.utils import replace_link_variables_by_paths -from plone.outputfilters.browser.resolveuid import uuidToURL from plone.restapi.deserializer import json_body from plone.restapi.imaging import get_scale_infos from plone.restapi.interfaces import ISerializeToJsonSummary from plone.restapi.serializer.summary import ( DefaultJSONSummarySerializer as BaseSerializer, ) +from plone.restapi.serializer.utils import uid_to_url from redturtle.volto.interfaces import IRedturtleVoltoLayer from zope.component import adapter from zope.interface import implementer from zope.interface import Interface -import re - - -RESOLVEUID_RE = re.compile(".*?/resolve[Uu]id/([^/]*)/?(.*)$") EMPTY_STRINGS = ["None"] @@ -89,19 +85,13 @@ def get_remote_url(self): # it isn't an internal link, so we can return it return value path = replace_link_variables_by_paths(context=self.context, url=value) - match = RESOLVEUID_RE.match(path) - if match: - uid, suffix = match.groups() - return uuidToURL(uid) - else: - portal = api.portal.get() - try: - ref_obj = portal.restrictedTraverse(path, None) - if ref_obj: - return ref_obj.absolute_url() - except Exception: - return "" - return "" + + url = uid_to_url(path) + + if url == path: + # something wrong with the path, maybe a missing object? + return "" + return url def __call__(self, force_all_metadata=False): if force_all_metadata: diff --git a/src/redturtle/volto/tests/test_resolveuid_re_patch.py b/src/redturtle/volto/tests/test_resolveuid_re_patch.py new file mode 100644 index 00000000..ec916706 --- /dev/null +++ b/src/redturtle/volto/tests/test_resolveuid_re_patch.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from plone import api +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.restapi.serializer.utils import uid_to_url +from redturtle.volto.testing import REDTURTLE_VOLTO_FUNCTIONAL_TESTING + +import unittest + + +class TestRESOLVEUIDREPatch(unittest.TestCase): + layer = REDTURTLE_VOLTO_FUNCTIONAL_TESTING + + def setUp(self): + self.app = self.layer["app"] + self.portal = self.layer["portal"] + self.portal_url = self.portal.absolute_url() + + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + + self.document = api.content.create( + container=self.portal, + type="Document", + title="Document", + ) + + def test_uuid_to_url_with_link_pattern(self): + path = f"/Plone/resolveuid/{self.document.UID()}" + + res = uid_to_url(path) + self.assertEqual(res, self.document.absolute_url()) + + def test_uuid_to_url_with_link_pattern_with_suffix(self): + path = f"/Plone/resolveuid/{self.document.UID()}/@@download/file" + + res = uid_to_url(path) + self.assertEqual(res, f"{self.document.absolute_url()}/@@download/file")