def test_source_object_unpublished(self): self.loginAsPortalOwner() wft = getToolByName(self.portal, 'portal_workflow') # create source object and related with proxy p1 = self._createType(self.portal, 'resonate.proxy', 'p1') p2 = self._createType(self.portal, 'resonate.proxy', 'p2') # Event source object s1 = self._createType(self.portal, 'Event', 's1') referenceable.IReferenceable(s1).addReference( referenceable.IReferenceable(p1), relationship='current_syndication_targets') referenceable.IReferenceable(s1).addReference( referenceable.IReferenceable(p2), relationship='current_syndication_targets') wft.doActionFor(s1, "publish") self.failUnless(wft.getInfoFor(s1, "review_state") == "published") self.failUnless(wft.getInfoFor(p1, "review_state") != "published") self.failUnless(wft.getInfoFor(p2, "review_state") != "published") wft.doActionFor(p1, "publish") self.failUnless(wft.getInfoFor(p1, "review_state") == "published") wft.doActionFor(p2, "publish") self.failUnless(wft.getInfoFor(p2, "review_state") == "published") wft.doActionFor(s1, "retract") self.failUnless(wft.getInfoFor(s1, "review_state") != "published") self.failUnless(wft.getInfoFor(p1, "review_state") != "published") self.failUnless(wft.getInfoFor(p2, "review_state") != "published") self.logout()
def test_portal_referencable(self): """ The portal supports Archetypes references. """ portal_uid = uuid_ifaces.IUUID(self.portal) self.assertTrue(portal_uid, 'Missing portal UID') uid_brains = self.portal.uid_catalog(UID=portal_uid) self.assertEqual(len(uid_brains), 1, 'Wrong number of portal UID results in the catalog') portal_refs = referenceable.IReferenceable(self.portal) corge_news = self._createType(self.portal, 'News Item', 'corge-news-title') corge_refs = referenceable.IReferenceable(corge_news) portal_refs.addReference(corge_refs, relationship='from-portal') corge_refs.addReference(portal_refs, relationship='to-portal') self.assertTrue(portal_refs.getRefs('from-portal'), 'Wrong number of refs from portal') self.assertTrue(portal_refs.getBRefs('to-portal'), 'Wrong number of refs to portal') self.assertTrue(corge_refs.getBRefs('from-portal'), 'Wrong number of refs from portal') self.assertTrue(corge_refs.getRefs('to-portal'), 'Wrong number of refs to portal')
def reject_syndication(obj, event): """ Update the source object's rejected_syndication_sites with a reference to the proxy object's site and remove proxy object. """ # Bail out if this isn't our workflow if event.workflow.id != 'syndication_proxy_workflow': return # and not our transition transition_id = event.transition and event.transition.id or None if transition_id != 'reject_syndication': return workflow = getToolByName(obj, 'portal_workflow') organization_path = getNavigationRoot(obj) organization = obj.restrictedTraverse(organization_path) source = utils.get_proxy_source(obj) referenceable.IReferenceable(source).addReference( referenceable.IReferenceable(organization), relationship='rejected_syndication_sites') referenceable.IReferenceable(source).deleteReference( referenceable.IReferenceable(obj), relationship='current_syndication_targets') # Use the workflow object's doActionFor so that IAfterTransitionEvent # gets fired correctly sudo(workflow.doActionFor, source, 'review_syndication') # Remove the proxy for this syndication request aq_parent(obj).manage_delObjects([obj.getId()])
def make_proxy( obj, event, target, suffix=''): """ Create a proxy in a target for a given syndication action. """ portal_properties = getToolByName(obj, 'portal_properties') encoding = portal_properties.site_properties.getProperty( 'default_charset', 'utf-8') workflow = getToolByName(obj, 'portal_workflow') unique_id = INameChooser(target)._findUniqueName( obj.getId() + suffix, None) proxy = sudo(target.invokeFactory, type_name='resonate.proxy', id=unique_id) proxy = target[proxy] proxy.title = obj.Title().decode(encoding) proxy.description = obj.Description().decode(encoding) proxy.source_type = obj.portal_type # Submit for publication, so the item shows up in the review list sudo(workflow.doActionFor, proxy, 'submit') # Set proxy to pending syndication so reviewer can accept/reject; # Use the workflow object's doActionFor so that IAfterTransitionEvent # gets fired correctly referenceable.IReferenceable(obj).addReference( referenceable.IReferenceable(proxy), relationship='current_syndication_targets') if event_behaviors.IEventBasic.providedBy(obj): for attr in ('start', 'end'): prop = getattr(obj, attr) if callable(prop): prop = DT2dt(prop()) setattr(proxy, attr, prop) sudo(workflow.doActionFor, proxy, event.transition.id)
def test_reject_syndication_transition(self): self.loginAsPortalOwner() wft = getToolByName(self.portal, 'portal_workflow') types = [ ('Event', 'events', lambda x: referenceable.IReferenceable(x). getRefs(relationship='rejected_syndication_sites')), ('News Item', 'news', lambda x: referenceable.IReferenceable(x). getRefs(relationship='rejected_syndication_sites')), ] for idx, _type in enumerate(types): typename, target, rejected_sites = _type _id = '%s_obj' + str(idx) # create source object and two organization folders s1 = self._createType(self.portal, typename, _id % 's1') c1 = self._createChildSiteAndTarget(self.portal, _id % 'c1', target) self.assertFalse(rejected_sites(s1)) # perform reject_syndication transition wft.doActionFor(s1, "request_syndication", organizations=IUUID(c1)) p1 = c1[target][s1.id] wft.doActionFor(p1, "reject_syndication") self.assertEqual(len(rejected_sites(s1)), 1) self.assertNotIn(p1.getId(), c1[target].objectIds(), 'Proxy remains after rejection') self.logout()
def test_proxy_object_removed(self): # create source object and related with proxy p1 = self._createType(self.portal, 'resonate.proxy', 'p1') p2 = self._createType(self.portal, 'resonate.proxy', 'p2') # Event source object s1 = self._createType(self.portal, 'Event', 's1') self.assertFalse( referenceable.IReferenceable(s1).getRefs( relationship='current_syndication_targets')) referenceable.IReferenceable(s1).addReference( referenceable.IReferenceable(p1), relationship='current_syndication_targets') self.portal.manage_delObjects(ids=['p1']) self.assertFalse( referenceable.IReferenceable(s1).getRefs( relationship='current_syndication_targets')) # News Item source object s2 = self._createType(self.portal, 'News Item', 's2') self.assertFalse( referenceable.IReferenceable(s1).getRefs( relationship='current_syndication_targets')) referenceable.IReferenceable(s2).addReference( referenceable.IReferenceable(p2), relationship='current_syndication_targets') self.portal.manage_delObjects(ids=['p2']) self.assertFalse( referenceable.IReferenceable(s2).getRefs( relationship='current_syndication_targets'))
def fix_organization_by_state(self, payload): wft = getToolByName(self.context, 'portal_workflow') source = uuidToObject(payload['object_uid']) if not source: return payload # we need to update the organization only for NON pending states if ('pending_syndication' in wft.getInfoFor( source, 'syndication_state') or 'pending_move' in wft.getInfoFor(source, 'syndication_move_state')): return payload if IProxy.providedBy(source): return payload proxies = referenceable.IReferenceable(source).getRefs( relationship='current_syndication_targets') organization_title = [] for proxy in proxies: new_organization = getNavigationRootObject(proxy, self.context) organization_title.append(new_organization.title_or_id()) payload['organization_title'] = ','.join(organization_title) return payload
def update_proxy_fields(obj, event): """Update proxy title when source title is modified """ proxies = referenceable.IReferenceable(obj).getRefs( relationship='current_syndication_targets') if not proxies: return portal_properties = getToolByName(obj, 'portal_properties') encoding = portal_properties.site_properties.getProperty('default_charset', 'utf-8') source_title = obj.title_or_id() if not isinstance(source_title, unicode): source_title = unicode(obj.title_or_id(), encoding) for proxy in proxies: reindex = False if not IProxy.providedBy(proxy): continue if source_title != proxy.title: proxy.title = source_title reindex = True elif event_behaviors.IEventBasic.providedBy(obj): if obj.start != proxy.start: proxy.start = obj.start reindex = True if obj.end != proxy.end: proxy.end = obj.end reindex = True if reindex: proxy.reindexObject()
def test_referenceable_api(self): doc1 = self.portal['doc1'] doc2 = self.portal['doc2'] doc3 = self.portal['doc3'] adapter1 = referenceable.IReferenceable(doc1) adapter2 = referenceable.IReferenceable(doc2) adapter3 = referenceable.IReferenceable(doc3) adapter1.addReference(adapter2, relationship='alpha') adapter3.addReference(adapter1, relationship='beta') self.assertEquals([doc2], adapter1.getRefs()) self.assertEquals([doc3], adapter1.getBRefs()) # Just an alias self.assertEquals(adapter1.getRefs(), adapter1.getReferences()) self.assertEquals(adapter1.getBRefs(), adapter1.getBackReferences()) # ReferenceObjects references = adapter1.getReferenceImpl() self.assertEquals(1, len(references)) self.assertEquals(doc1, references[0].getSourceObject().context) self.assertEquals(doc2, references[0].getTargetObject().context) self.assertEquals('alpha', references[0].relationship) references = adapter1.getBackReferenceImpl() self.assertEquals(1, len(references)) self.assertEquals(doc3, references[0].getSourceObject().context) self.assertEquals(doc1, references[0].getTargetObject().context) self.assertEquals('beta', references[0].relationship) self.assertEquals(IUUID(doc1), adapter1.UID()) self.assertTrue('lookupObject?uuid' in adapter1.reference_url()) self.assertTrue(adapter1.hasRelationshipTo(adapter2)) self.assertFalse(adapter1.hasRelationshipTo(adapter3)) # This has been tested implicitly # self.assertEquals('x', adapter1.addReference()) self.assertEquals(['alpha'], adapter1.getRelationships()) adapter1.deleteReference(adapter2) self.assertFalse(adapter1.hasRelationshipTo(adapter2)) adapter1.addReference(adapter2, relationship='alpha') adapter1.deleteReferences('alpha') self.assertFalse(adapter1.hasRelationshipTo(adapter2))
def test_auto_approve_form(self): """ The auto-approve action and form set references. """ foo_child_site = self._createChildSiteAndTarget(self.portal, 'foo-child-site', 'target', title='Foo Child Site') bar_child_site = self._createChildSiteAndTarget(self.portal, 'bar-child-site', 'target', title='Bar Child Site') qux_child_site = self._createChildSiteAndTarget( self.portal, 'qux-child-site', 'target') transaction.commit() self.setUpBrowser() self.browser.open(self.portal.absolute_url()) self.browser.getLink( 'Designate Syndication Auto-Approve Targets').click() form = self.browser.getForm('resonate.auto-approve') news_ctl = form.getControl(name='News Item:list') news_ctl.getControl(foo_child_site.Title()).selected = True self.assertFalse( news_ctl.getControl(bar_child_site.Title()).selected, 'Child site selected by default') form.getControl('Designate Auto-Approve Sites').click() self.assertEqual(self.browser.url, self.portal.absolute_url(), 'Wrong redirect after designating child sites') self.assertIn('Auto-approve target sites designated successfully', self.browser.contents, 'Wrong or missing success message') self.browser.getLink( 'Designate Syndication Auto-Approve Targets').click() form = self.browser.getForm('resonate.auto-approve') news_ctl = form.getControl(name='News Item:list') news_ctl.getControl(qux_child_site.getId()).selected = True form.getControl('Designate Auto-Approve Sites').click() self.assertIn('Auto-approve target sites designated successfully', self.browser.contents, 'Wrong or missing success message') portal_refs = referenceable.IReferenceable(self.portal) news_refs = portal_refs.getRefs('resonate.auto-approve.News Item') self.assertEqual( news_refs, [foo_child_site, qux_child_site], 'Wrong auto-approve references after submitting form') event_refs = portal_refs.getRefs('resonate.auto-approve.Event') self.assertFalse(event_refs, 'Auto-approve references set for wrong type') self.browser.getLink( 'Designate Syndication Auto-Approve Targets').click() form = self.browser.getForm('resonate.auto-approve') news_ctl = form.getControl(name='News Item:list') self.assertTrue( news_ctl.getControl(foo_child_site.Title()).selected, 'Existing values not preserved on form')
def get_back_references_from_AT_type(self): """ Returns not expired back references for Archetypes items """ referenceable_item = referenceable.IReferenceable(self.context) result = [] for rel in referenceable_item.getBRefs(): if checkPermission('zope2.View', rel) and not rel.isExpired(): result.append(rel) return result
def get_proxy_source(proxy): """ Retrieve the proxy's source via the back reference. """ brefs = referenceable.IReferenceable(proxy).getBRefs( relationship='current_syndication_targets') if len(brefs) > 0: assert len(brefs) == 1, ( 'More than one back syndication reference for proxy') return brefs[0]
def is_moved(self): """ Determine if this source has been accepted to be moved. """ workflow = getToolByName(self.context, 'portal_workflow') source = self.context targets = referenceable.IReferenceable(source).getRefs( relationship='current_syndication_targets') return bool([ target for target in targets if workflow.getInfoFor( target, 'syndication_move_state') == 'moved'])
def test_accept_syndication_transition(self): self.loginAsPortalOwner() wft = getToolByName(self.portal, 'portal_workflow') types = [ ('Event', 'events', lambda x: referenceable.IReferenceable(x). getRefs(relationship='current_syndication_targets')), ('News Item', 'news', lambda x: referenceable.IReferenceable(x). getRefs(relationship='current_syndication_targets')), ] for idx, _type in enumerate(types): typename, target, syndication_targets = _type _id = '%s_obj' + str(idx) # create source object and two organization folders s1 = self._createType(self.portal, typename, _id % 's1') c1 = self._createChildSiteAndTarget(self.portal, _id % 'c1', target) c2 = self._createChildSiteAndTarget(self.portal, _id % 'c2', target) # perform accept_syndication transition wft.doActionFor(s1, "request_syndication", organizations=[IUUID(c1), IUUID(c2)]) self.assertTrue(c1[target].objectIds()) self.assertTrue(c2[target].objectIds()) p1 = c1[target].objectValues()[0] doActionFor(wft, p1, "accept_syndication") p2 = c2[target].objectValues()[0] doActionFor(wft, p2, "accept_syndication") self.assertEqual(IUUID(utils.get_proxy_source(p1)), IUUID(s1)) self.assertEqual(IUUID(utils.get_proxy_source(p2)), IUUID(s1)) self.assertEqual(len(syndication_targets(s1)), 2) self.logout()
def is_pending_move(self): """ Determine if this source has any pending requests for move. """ workflow = getToolByName(self.context, 'portal_workflow') source = self.context targets = referenceable.IReferenceable(source).getRefs( relationship='current_syndication_targets') return bool([ target for target in targets if workflow.getInfoFor( target, 'syndication_move_state') == 'pending_move'])
def target_proxies(self): pc = getToolByName(self, 'portal_catalog') current_syndication_targets = referenceable.IReferenceable( self.context).getRefs(relationship='current_syndication_targets') kw = dict( portal_type='resonate.proxy', UID=[api.content.get_uuid(t) for t in current_syndication_targets], ) if self.organization_uids: # Verify this object has not already been syndicated to the # requested organization kw['navigation_root_uuid'] = self.organization_uids target_proxies = pc(**kw) return target_proxies
def test_source_object_title_modified(self): # create source object and related with proxy p1 = self._createType(self.portal, 'resonate.proxy', 'p1') p2 = self._createType(self.portal, 'resonate.proxy', 'p2') p3 = self._createType(self.portal, 'resonate.proxy', 'p3') p4 = self._createType(self.portal, 'resonate.proxy', 'p4') # Event source object s1 = self._createType(self.portal, 'Event', 's1') s1.setTitle('Old title') notify(ObjectModifiedEvent(s1)) referenceable.IReferenceable(s1).addReference( referenceable.IReferenceable(p1), relationship='current_syndication_targets') referenceable.IReferenceable(s1).addReference( referenceable.IReferenceable(p2), relationship='current_syndication_targets') self.assertNotEqual(p1.title, 'New title') self.assertNotEqual(p2.title, 'New title') s1.setTitle('New title') notify(ObjectModifiedEvent(s1)) self.assertEqual(p1.title, 'New title') self.assertEqual(p2.title, 'New title') # News Item source object s2 = self._createType(self.portal, 'News Item', 's2') s2.setTitle('Old title') notify(ObjectModifiedEvent(s2)) referenceable.IReferenceable(s2).addReference( referenceable.IReferenceable(p3), relationship='current_syndication_targets') referenceable.IReferenceable(s2).addReference( referenceable.IReferenceable(p4), relationship='current_syndication_targets') self.assertNotEqual(p3.title, 'New title') self.assertNotEqual(p4.title, 'New title') s2.setTitle('New title') notify(ObjectModifiedEvent(s2)) self.assertEqual(p3.title, 'New title') self.assertEqual(p4.title, 'New title')
def unpublish_proxy(obj, event): """Unpublish proxy after source object is unpublished """ proxies = referenceable.IReferenceable(obj).getRefs( relationship='current_syndication_targets') if not proxies: return old_state = event.old_state.id if old_state != 'published': return wft = getToolByName(obj, 'portal_workflow') for proxy in proxies: if wft.getInfoFor(proxy, "review_state") == "published": sudo(wft.doActionFor, proxy, 'retract')
def is_syndication_auto_approved(self): """ Is syndication approved from the source to this target site and type. """ portal = getToolByName(self.context, 'portal_url').getPortalObject() proxy = self.context target_site = root.getNavigationRootObject(proxy, portal) source = utils.get_proxy_source(proxy) source_site = root.getNavigationRootObject(source, portal) return source_site in referenceable.IReferenceable( target_site).getBRefs( relationship=self.RELATIONSHIP_TEMPLATE.format( source.getPortalTypeName()))
def test_source_object_removed(self): # create source object and related with proxy p1 = self._createType(self.portal, 'resonate.proxy', 'p1') p2 = self._createType(self.portal, 'resonate.proxy', 'p2') p3 = self._createType(self.portal, 'resonate.proxy', 'p3') p4 = self._createType(self.portal, 'resonate.proxy', 'p4') # Event source object s1 = self._createType(self.portal, 'Event', 's1') referenceable.IReferenceable(s1).addReference( referenceable.IReferenceable(p1), relationship='current_syndication_targets') referenceable.IReferenceable(s1).addReference( referenceable.IReferenceable(p2), relationship='current_syndication_targets') notify(ObjectModifiedEvent(p1)) notify(ObjectModifiedEvent(p2)) self.portal.manage_delObjects(ids=['s1']) self.assertNotIn('p1', self.portal.objectIds()) self.assertNotIn('p2', self.portal.objectIds()) # Seminar source object s2 = self._createType(self.portal, 'News Item', 's2') referenceable.IReferenceable(s2).addReference( referenceable.IReferenceable(p3), relationship='current_syndication_targets') referenceable.IReferenceable(s2).addReference( referenceable.IReferenceable(p4), relationship='current_syndication_targets') notify(ObjectModifiedEvent(p3)) notify(ObjectModifiedEvent(p4)) self.portal.manage_delObjects(ids=['s2']) self.assertNotIn('p3', self.portal.objectIds()) self.assertNotIn('p4', self.portal.objectIds())
def _get_targets_by_state(self, state): proxies = referenceable.IReferenceable( self.context).getRefs(relationship='current_syndication_targets') organization_paths = set() wft = getToolByName(self.context, 'portal_workflow') for proxy in proxies: status = wft.getInfoFor(proxy, 'review_state') if status != state: continue path = getNavigationRoot(proxy) if not path: continue organization_paths.add(path) organizations = [] for path in organization_paths: try: organizations.append(self.context.restrictedTraverse(path)) except Unauthorized: pass return organizations
def getTargetObject(self): obj = self._optimizedGetObject(self.targetUID) if obj and not referenceable.IReferenceable.providedBy(obj): obj = referenceable.IReferenceable(obj) return obj
def test_auto_approve_workflow(self): """ The auto-approve automatic transition applies as appropriate. """ foo_child_site = self._createChildSiteAndTarget(self.portal, 'foo-child-site', 'target', title='Foo Child Site') bar_child_site = self._createChildSiteAndTarget(self.portal, 'bar-child-site', 'target', title='Bar Child Site') qux_child_site = self._createChildSiteAndTarget(self.portal, 'qux-child-site', 'target', title='Qux Child Site') portal_refs = referenceable.IReferenceable(self.portal) for child_site in (foo_child_site, qux_child_site): portal_refs.addReference( referenceable.IReferenceable(child_site), relationship='resonate.auto-approve.News Item') corge_news = self._createType(self.portal, 'News Item', 'corge-news-title') grault_event = self._createType(self.portal, 'Event', 'grault-event') # Request and approve the non-auto-approve site first so that we can # confirm auto-approval triggers the state change on the source # objects when all requests are approved. workflow = getToolByName(self.portal, 'portal_workflow') for content in corge_news, grault_event: workflow.doActionFor( content, "request_syndication", organizations=[uuid_ifaces.IUUID(bar_child_site)]) news_state = workflow.getInfoFor( bar_child_site.target[corge_news.getId()], 'syndication_state') self.assertEqual(news_state, 'pending_syndication', 'Wrong unapproved syndication workflow state') self.assertEqual(workflow.getInfoFor(corge_news, 'syndication_state'), 'pending_syndication', 'Wrong unapproved syndication source workflow state') self.setRoles(('Manager', )) workflow.doActionFor(bar_child_site.target[corge_news.getId()], "accept_syndication") for content in corge_news, grault_event: workflow.doActionFor(content, "request_syndication", organizations=[ uuid_ifaces.IUUID(foo_child_site), uuid_ifaces.IUUID(qux_child_site) ]) for child_site in [foo_child_site, bar_child_site, qux_child_site]: for content in corge_news, grault_event: self.assertIn( content.getId(), child_site.target.objectIds(), 'Content missing from target site after request') news_proxy = child_site.target[corge_news.getId()] self.assertEqual( workflow.getInfoFor(news_proxy, 'syndication_state'), 'syndicated', 'Wrong auto-approved syndication workflow state') self.assertEqual(workflow.getInfoFor(news_proxy, 'review_state'), 'published', 'Wrong auto-approved syndication workflow state') self.assertEqual( workflow.getInfoFor(corge_news, 'syndication_state'), 'syndicated', 'Wrong auto-approved syndicated source workflow state') event_state = workflow.getInfoFor( child_site.target[grault_event.getId()], 'syndication_state') self.assertEqual(event_state, 'pending_syndication', 'Wrong unapproved syndication workflow state') for child_site in [foo_child_site, qux_child_site]: news_state = workflow.getInfoFor( child_site.target[corge_news.getId()], 'syndication_state') self.assertEqual(news_state, 'syndicated', 'Wrong auto-approved syndication workflow state')
def rejected_syndications(self): rejected = referenceable.IReferenceable( self.context).getRefs(relationship='rejected_syndication_sites') return rejected