diff --git a/news/410.feature b/news/410.feature new file mode 100644 index 00000000..1ad25924 --- /dev/null +++ b/news/410.feature @@ -0,0 +1,2 @@ +Provide an IContentListingObject adapter +[erral] diff --git a/plone/app/event/adapters.py b/plone/app/event/adapters.py new file mode 100644 index 00000000..0c6a64b4 --- /dev/null +++ b/plone/app/event/adapters.py @@ -0,0 +1,20 @@ +from plone.app.contentlisting.interfaces import IContentListingObject +from plone.app.contentlisting.realobject import RealContentListingObject +from zope.interface import implementer + + +@implementer(IContentListingObject) +class OccurrenceContentListingObject(RealContentListingObject): + + def __getattr__(self, name): + """We'll override getattr so that we can defer name lookups to + the real underlying objects without knowing the names of all + attributes. + """ + if name.startswith("_"): + raise AttributeError(name) + obj = self.getObject() + # we need to override the behavior of RealContentListingObject + # because Occurrence objects rely on acquisition to show their title + # and other attributes + return getattr(obj, name) diff --git a/plone/app/event/configure.zcml b/plone/app/event/configure.zcml index e546895c..edf0399a 100644 --- a/plone/app/event/configure.zcml +++ b/plone/app/event/configure.zcml @@ -67,4 +67,11 @@ name="plone.app.event" /> + + + diff --git a/plone/app/event/tests/test_recurrence.py b/plone/app/event/tests/test_recurrence.py index 21e5a1cd..34451906 100644 --- a/plone/app/event/tests/test_recurrence.py +++ b/plone/app/event/tests/test_recurrence.py @@ -1,6 +1,8 @@ from OFS.SimpleItem import SimpleItem +from plone.app.contentlisting.interfaces import IContentListingObject from plone.app.event.base import get_events from plone.app.event.base import RET_MODE_ACCESSORS +from plone.app.event.base import RET_MODE_OBJECTS from plone.app.event.dx.traverser import OccurrenceTraverser from plone.app.event.recurrence import Occurrence from plone.app.event.testing import PAEvent_INTEGRATION_TESTING @@ -352,3 +354,55 @@ def test_recurrence_occurrences_with_range_start_and_end(self): # Subsequent ones are IOccurrence objects self.assertTrue(IOccurrence.providedBy(result[1])) + + +class TestRecurrenceContentListingSupport(unittest.TestCase): + """test that content listing objects are correctly serialized in plone.app.contentlisting objects""" + + layer = PAEventDX_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer["portal"] + self.request = self.layer["request"] + + set_browserlayer(self.request) + set_env_timezone(TZNAME) + set_timezone(TZNAME) + + now = patched_now() + + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + self.daily = createContentInContainer( + self.portal, + "plone.app.event.dx.event", + id="daily", + title="Daily Event", + start=now, + end=now + datetime.timedelta(hours=1), + location="Vienna", + recurrence="RRULE:FREQ=DAILY;COUNT=4", + ) + + def test_recurrence_objects_adapted_to_content_listing_objects(self): + res = get_events(self.portal, ret_mode=RET_MODE_OBJECTS, expand=True) + + self.assertEqual(len(res), 4) + + first_item = res[0] + second_item = res[1] + + first_content_listing_object = IContentListingObject(first_item) + second_content_listing_object = IContentListingObject(second_item) + + self.assertEqual(first_content_listing_object.Title(), first_item.Title()) + self.assertEqual(second_content_listing_object.Title(), second_item.Title()) + + self.assertEqual(first_content_listing_object.start, first_item.start) + self.assertEqual(second_content_listing_object.start, second_item.start) + + self.assertEqual(first_content_listing_object.end, first_item.end) + self.assertEqual(second_content_listing_object.end, second_item.end) + + self.assertTrue( + first_content_listing_object.start < second_content_listing_object.start + )