def sync_task(obj, event): """Index the given task in opengever.globalindex. """ if IContainerModifiedEvent.providedBy(event): return TaskSqlSyncer(obj, event).sync()
def version(context, event): # only version the modified object, not its container on modification if IContainerModifiedEvent.providedBy(event): return # Hack for stagingbehavior, which triggers a event with a aq_based context # when deleting the working copy try: pr = context.portal_repository except AttributeError: return if not pr.isVersionable(context): return try: create_version = not pr.isUpToDate( context, aq_base(context).version_id, ) except (AttributeError, ArchivistError): # The object is not actually registered, but a version is # set, perhaps it was imported, or versioning info was # inappropriately destroyed create_version = True # create new version if needed if create_version: pr.save(obj=context, comment=event.action)
def element_modified(obj, event): if IContainerModifiedEvent.providedBy(event): for element in _get_children(obj): if getattr(element, "__created", False) is True: delattr(element, "__created") element_modified(element, None) elements = [] link_objects = [] for obj in iterate_until_root(obj): elements.append(obj.id) intids = getUtility(IIntIds) to_id = intids.queryId(obj) if to_id: catalog = getUtility(ICatalog) links = catalog.findRelations({ "to_id": to_id, "from_attribute": "symbolic_link" }) for link in links: link_objects.append(link.from_object) if link_objects: # We found a link we do not want to iterate over link parents break elements = elements[:-1] reindex_symlink(link_objects, elements)
def plonegroup_contact_changed(organization, event): """ Manage an organization change """ # zope.lifecycleevent.ObjectRemovedEvent : delete # zope.lifecycleevent.ObjectModifiedEvent : edit, rename # is the container who's modified at creation ? # bypass if we are removing the Plone Site if IContainerModifiedEvent.providedBy(event) or \ event.object.portal_type == 'Plone Site': return # invalidate vocabularies caches invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.CreatingGroupVocabulary') invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.ActiveCreatingGroupVocabulary') invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.TreatingGroupsWithDeactivatedVocabulary') invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.TreatingGroupsForFacetedFilterVocabulary') # is the current organization a part of own organization organization_path = '/'.join(organization.getPhysicalPath()) if not organization_path.startswith(get_own_organization_path('unfound')): return portal = api.portal.getSite() pcat = portal.portal_catalog brains = pcat.unrestrictedSearchResults(portal_type='organization', path=organization_path) for brain in brains: obj = brain._unrestrictedGetObject() full_title = obj.get_full_title(separator=' - ', first_index=1) for base_folder in (portal['templates']['om'], portal.contacts['contact-lists-folder']): folder = base_folder.get(brain.UID) if folder and folder.title != full_title: folder.title = full_title folder.reindexObject(idxs=['Title', 'SearchableText', 'sortable_title']) modified(folder)
def testRenameEvents(self): self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('monty',), ('python',)) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('foo', 'monty'), ('bar', 'python')) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeMovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].newName, 'bar') self.assertEqual(self.reflecto.manage_renameObjects(('foo',), ('bar',)), ['foo']) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[1])) self.assertTrue(IObjectMovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertEqual(events[2].newName, 'bar') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def testRenameEvents(self): self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('monty', ), ('python', )) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('foo', 'monty'), ('bar', 'python')) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeMovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].newName, 'bar') self.assertEqual( self.reflecto.manage_renameObjects(('foo', ), ('bar', )), ['foo']) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[1])) self.assertTrue(IObjectMovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertEqual(events[2].newName, 'bar') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def test_events(self): from OFS.interfaces import IObjectWillBeAddedEvent from zope.component import adapter from zope.component import provideHandler from zope.container.interfaces import IContainerModifiedEvent from zope.container.interfaces import IObjectAddedEvent from zope.lifecycleevent.interfaces import IObjectCreatedEvent events = [] @adapter(IObjectCreatedEvent) def _handleObjectCreated(event): events.append(event) provideHandler(_handleObjectCreated) @adapter(IObjectWillBeAddedEvent) def _handleObjectWillBeAdded(event): events.append(event) provideHandler(_handleObjectWillBeAdded) @adapter(IObjectAddedEvent) def _handleObjectAdded(event): events.append(event) provideHandler(_handleObjectAdded) @adapter(IContainerModifiedEvent) def _handleContainerModified(event): events.append(event) provideHandler(_handleContainerModified) self.ti.constructInstance(self.f, 'foo') self.assertEqual(len(events), 4) evt = events[0] self.assertTrue(IObjectCreatedEvent.providedBy(evt)) self.assertEqual(evt.object, self.f.foo) evt = events[1] self.assertTrue(IObjectWillBeAddedEvent.providedBy(evt)) self.assertEqual(evt.object, self.f.foo) self.assertEqual(evt.oldParent, None) self.assertEqual(evt.oldName, None) self.assertEqual(evt.newParent, self.f) self.assertEqual(evt.newName, 'foo') evt = events[2] self.assertTrue(IObjectAddedEvent.providedBy(evt)) self.assertEqual(evt.object, self.f.foo) self.assertEqual(evt.oldParent, None) self.assertEqual(evt.oldName, None) self.assertEqual(evt.newParent, self.f) self.assertEqual(evt.newName, 'foo') evt = events[3] self.assertTrue(IContainerModifiedEvent.providedBy(evt)) self.assertEqual(evt.object, self.f)
def roleModified(obj, event): """Project team has been modified subscriber's handler. obj: team instance,a project node event:objectModifiedevent todo:build a receivers list to avoid send repeat """ if IContainerModifiedEvent.providedBy(event): return filteAndSend(obj)
def test_events(self): from OFS.interfaces import IObjectWillBeAddedEvent from zope.component import adapter from zope.component import provideHandler from zope.container.interfaces import IContainerModifiedEvent from zope.container.interfaces import IObjectAddedEvent from zope.lifecycleevent.interfaces import IObjectCreatedEvent events = [] @adapter(IObjectCreatedEvent) def _handleObjectCreated(event): events.append(event) provideHandler(_handleObjectCreated) @adapter(IObjectWillBeAddedEvent) def _handleObjectWillBeAdded(event): events.append(event) provideHandler(_handleObjectWillBeAdded) @adapter(IObjectAddedEvent) def _handleObjectAdded(event): events.append(event) provideHandler(_handleObjectAdded) @adapter(IContainerModifiedEvent) def _handleContainerModified(event): events.append(event) provideHandler(_handleContainerModified) self.ti.constructInstance(self.f, 'foo') self.assertEquals(len(events), 4) evt = events[0] self.failUnless(IObjectCreatedEvent.providedBy(evt)) self.assertEquals(evt.object, self.f.foo) evt = events[1] self.failUnless(IObjectWillBeAddedEvent.providedBy(evt)) self.assertEquals(evt.object, self.f.foo) self.assertEquals(evt.oldParent, None) self.assertEquals(evt.oldName, None) self.assertEquals(evt.newParent, self.f) self.assertEquals(evt.newName, 'foo') evt = events[2] self.failUnless(IObjectAddedEvent.providedBy(evt)) self.assertEquals(evt.object, self.f.foo) self.assertEquals(evt.oldParent, None) self.assertEquals(evt.oldName, None) self.assertEquals(evt.newParent, self.f) self.assertEquals(evt.newName, 'foo') evt = events[3] self.failUnless(IContainerModifiedEvent.providedBy(evt)) self.assertEquals(evt.object, self.f)
def testCutEvents(self): cp = self.reflecto.manage_cutObjects(('foo', )) self.reflecto['subdir'].manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[0])) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].oldParent, self.reflecto) self.assertEqual(events[0].newName, 'foo') self.assertEqual(events[0].newParent, self.reflecto['subdir']) self.assertTrue(IObjectMovedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertEqual(events[2].object, self.reflecto) self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertEqual(events[3].object, self.reflecto['subdir'])
def library_modified(obj, event): if IContainerModifiedEvent.providedBy(event): return catalog = portal_api.get_tool('portal_catalog') try: for brain in catalog.unrestrictedSearchResults( parent_libraries=content_api.get_uuid(obj)): o = brain._unrestrictedGetObject() o.reindexObject(idxs=['parent_libraries']) except Exception: logger.exception('An error in library_modified event handler')
def testCutEvents(self): cp = self.reflecto.manage_cutObjects(('foo',)) self.reflecto['subdir'].manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[0])) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].oldParent, self.reflecto) self.assertEqual(events[0].newName, 'foo') self.assertEqual(events[0].newParent, self.reflecto['subdir']) self.assertTrue(IObjectMovedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertEqual(events[2].object, self.reflecto) self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertEqual(events[3].object, self.reflecto['subdir'])
def propagate_vocab_restrictions_to_children(container, event): if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return restricted_fields = [ IClassification['classification'], IClassification['privacy_layer']] propagate_vocab_restrictions( container, event, restricted_fields, IClassificationMarker)
def index_and_update_author_modified_content(content, event): """A content have been created of modifed. Update its author information. """ # In the same way, we discard event on versioned content if they # are about adding or removing a version. if IVersionedContent.providedBy(content) and IContainerModifiedEvent.providedBy(event): return if getattr(content, "__initialization__", False): return ChangesTask.get().modified(content) ICataloging(content).reindex()
def store_activity(document, event): if IObjectInitializedEvent.providedBy(event): return elif IContainerModifiedEvent.providedBy(event): return elif not ILayer.providedBy(getattr(document, 'REQUEST', None)): return elif not IUUIDAware.providedBy(document): return folder = document.aq_parent get_tool().store_activity(folder, 'modify', uid=IUUID(document))
def propagate_vocab_restrictions_to_children(container, event): if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return restricted_fields = [ ILifeCycle['retention_period'], ILifeCycle['archival_value'], ILifeCycle['custody_period']] propagate_vocab_restrictions( container, event, restricted_fields, ILifeCycleMarker)
def propagate_vocab_restrictions_to_children(container, event): if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return restricted_fields = [ ILifeCycle['retention_period'], ILifeCycle['archival_value'], ILifeCycle['custody_period'] ] propagate_vocab_restrictions(container, event, restricted_fields, ILifeCycleMarker)
def set_roles_after_modifying(context, event): # Handle the modify event having been a removal of a related item setattr( context, 'relatedItems', [item for item in getattr(context, 'relatedItems', []) if item.to_object], ) if IContainerModifiedEvent.providedBy(event): return LocalRolesSetter(context).set_roles(event)
def disposition_modified(context, event): if IContainerModifiedEvent.providedBy(event): return # Skip modified events during dossier destruction if IDuringDossierDestruction.providedBy(context.REQUEST): return storage = IHistoryStorage(context) storage.add('edited', api.user.get_current().getId(), context.get_dossier_representations())
def create_version_on_save(context, event): """Creates a new version on a versionable object when the object is saved. A new version is created if the type is automatic versionable and has changed or if the user has entered a change note. """ # according to Products.CMFEditions' update_version_on_edit script # only version the modified object, not its container on modification if IContainerModifiedEvent.providedBy(event): return # XXX dirty hack for stagingbehavior, which triggers a event with # a aq_based context when deleting the working copy try: pr = context.portal_repository except AttributeError: return if not pr.isVersionable(context): # cancel, the object is not versionable return create_version = False if getattr(context, 'REQUEST', None): changeNote = get_change_note(context.REQUEST, None) else: changeNote = None if changeNote: # user has entered a change note. create a new version even if nothing # has changed. create_version = True elif pr.supportsPolicy(context, 'at_edit_autoversion'): # automatic versioning is enabled for this portal type if not base_hasattr(context, 'version_id'): # we do not have a initial version create_version = True else: try: create_version = not pr.isUpToDate(context, context.version_id) except ArchivistUnregisteredError: # The object is not actually registered, but a version is # set, perhaps it was imported, or versioning info was # inappropriately destroyed create_version = True # create new version if needed if create_version: pr.save(obj=context, comment=changeNote)
def index_and_update_author_modified_content(content, event): """A content have been created of modifed. Update its author information. """ # In the same way, we discard event on versioned content if they # are about adding or removing a version. if (IVersionedContent.providedBy(content) and IContainerModifiedEvent.providedBy(event)): return if getattr(content, '__initialization__', False): return ChangesTask.get().modified(content) ICataloging(content).reindex()
def todo_modified(todo, event): if IContainerModifiedEvent.providedBy(event): return if is_attribute_changed(event, "responsible", "IToDoSchema"): workspace = todo.get_containing_workspace() WorkspaceWatcherManager(workspace).todo_responsible_modified(todo) ToDoAssignedActivity(todo, getRequest()).record() if is_attribute_changed(event, "completed", "IToDoSchema"): if todo.completed: ToDoClosedActivity(todo, getRequest()).record() else: ToDoReopenedActivity(todo, getRequest()).record()
def update_reference_prefixes(obj, event): """A eventhandler which reindex all contained objects, if the reference prefix has been changed. """ if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return if is_reference_number_prefix_changed(event.descriptions): catalog = api.portal.get_tool('portal_catalog') children = catalog.unrestrictedSearchResults( path='/'.join(obj.getPhysicalPath())) for child in children: child.getObject().reindexObject(idxs=['reference'])
def set_roles_after_modifying(context, event): # Handle the modify event having been a removal of a related item setattr( context, 'relatedItems', [ item for item in getattr(context, 'relatedItems', []) if item.to_object ], ) if IContainerModifiedEvent.providedBy(event): return LocalRolesSetter(context).set_roles(event)
def testCopyEvents(self): cp = self.reflecto.manage_copyObjects(('foo',)) self.reflecto.manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 3) self.assertTrue(IObjectCopiedEvent.providedBy(events[0])) self.assertEqual(events[0].original.getId(), 'foo') self.assertEqual(events[0].object.getId(), 'copy_of_foo') self.assertTrue(IObjectClonedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'copy_of_foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertTrue(events[2].object is self.reflecto)
def testCopyEvents(self): cp = self.reflecto.manage_copyObjects(('foo', )) self.reflecto.manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 3) self.assertTrue(IObjectCopiedEvent.providedBy(events[0])) self.assertEqual(events[0].original.getId(), 'foo') self.assertEqual(events[0].object.getId(), 'copy_of_foo') self.assertTrue(IObjectClonedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'copy_of_foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertTrue(events[2].object is self.reflecto)
def adaptPloneGroupDefinition(organization, event): """ Manage an organization change """ # zope.lifecycleevent.ObjectRemovedEvent : delete # zope.lifecycleevent.ObjectModifiedEvent : edit, rename # is the container who's modified at creation ? # bypass if we are removing the Plone Site if IContainerModifiedEvent.providedBy(event) or \ event.object.portal_type == 'Plone Site': return # is the current organization a part of own organization organization_path = '/'.join(organization.getPhysicalPath()) if not organization_path.startswith( get_own_organization_path( not_found_value='unfound')): # can be unfound too return portal = getSite() # when an organization is removed (and its content), we check if it is used in plonegroup configuration registry_orgs = get_registry_organizations() if IObjectRemovedEvent.providedBy( event) and organization.UID() in registry_orgs: smi = IStatusMessage(organization.REQUEST) smi.addStatusMessage(_('You cannot delete this item !'), type='error') smi.addStatusMessage(_( "This organization or a contained organization is used in plonegroup " "configuration ! Remove it first from the configuration !"), type='error') view_url = getMultiAdapter((organization, organization.REQUEST), name=u'plone_context_state').view_url() organization.REQUEST['RESPONSE'].redirect(view_url) raise Redirect(view_url) return pcat = portal.portal_catalog brains = pcat(portal_type='organization', path=organization_path) changes = False for brain in brains: orga = brain.getObject() orga_uid = orga.UID() if orga_uid in registry_orgs: if addOrModifyOrganizationGroups(orga, orga_uid): changes = True if changes: invalidate_sopgv_cache() invalidate_sov_cache() invalidate_soev_cache() invalidate_ssoev_cache()
def create_title_from_id(obj, event): if not api.portal.get_registry_record( 'ploneintranet.workspace.rename_after_title_changed', default=True, ): return autosave_portal_types = api.portal.get_registry_record( 'ploneintranet.workspace.autosave_portal_types', default=[], ) if obj.portal_type in autosave_portal_types: # autosave does not work well with autorename because the form action # will point to the old URL and the redirection tool will not work # with the ajax calls return if IContainerModifiedEvent.providedBy(event): # The container modified event gets triggered during the creation # of a folder. We must not change the id before an item as been # properly created. return if IBaseWorkspaceFolder.providedBy(obj): # Don't change the ID of a workspace return if not in_workspace(obj): # Don't handle content outside of a workspace return orig_id = obj.getId() title_adapter = INameFromTitle(obj, None) name = title_adapter and title_adapter.title if not name: # No title present, no point in changing the id return if len(name) > MAX_ID_FROM_TITLE_LENGTH: plone_view = getMultiAdapter((obj, obj.REQUEST), name='plone') name = plone_view.cropText(name, MAX_ID_FROM_TITLE_LENGTH, ellipsis="") normalized_name = IUserPreferredURLNormalizer(obj.REQUEST).normalize(name) container = aq_parent(obj) # Check if the id is already looking good if _is_id_good_enough(orig_id, normalized_name, container): return chooser = INameChooser(container) new_id = chooser and chooser.chooseName(normalized_name, container) if new_id and new_id != orig_id: unlock_view = obj.restrictedTraverse('@@toggle-lock', None) if unlock_view and unlock_view.can_unlock(): unlock_view.unlock() api.content.rename(obj, new_id)
def update_favorites_title(context, event): """Event handler which updates the titles of all existing favorites for the current context, unless the title is personalized. """ if IContainerModifiedEvent.providedBy(event): return if ILocalrolesModifiedEvent.providedBy(event): return if is_title_changed(event.descriptions): query = Favorite.query.filter( and_(Favorite.oguid == Oguid.for_object(context), Favorite.is_title_personalized == False)) # noqa query.update_title(context.title) mark_changed(create_session())
def reindex_contained_objects(dossier, event): """When a dossier is modified, if the title has changed we reindex the corresponding index in all contained object (containing_dossier or containing_subdossier) """ if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return attrs = tuple(attr for descr in event.descriptions for attr in descr.attributes) if 'IOpenGeverBase.title' not in attrs: return if dossier.is_subdossier(): reindex_containing_subdossier_for_contained_objects(dossier, event) else: reindex_containing_dossier_for_contained_objects(dossier, event)
def saveReferenceNumberPrefix(obj, event): """When an object providing IReferenceNumberPrefixMarker (repository folders) gets added or has been modified, make sure it has a unique reference number prefix. If necessary, set_number() creates a collision free prefix. """ if IContainerModifiedEvent.providedBy(event): return parent = aq_parent(aq_inner(obj)) # Mark the reference number as issued in the parent's annotations number = PrefixAdapter(parent).set_number( obj, IReferenceNumberPrefix(obj).reference_number_prefix) # Store the number on the actual object IReferenceNumberPrefix(obj).reference_number_prefix = number
def reindex_contained_objects(dossier, event): """When a subdossier is modified, we update the ``containing_subdossier`` index of all contained objects (documents, mails and tasks) so they don't show an outdated title in the ``subdossier`` column """ if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return catalog = api.portal.get_tool('portal_catalog') parent = aq_parent(aq_inner(dossier)) is_subdossier = IDossierMarker.providedBy(parent) if is_subdossier: objects = catalog(path='/'.join(dossier.getPhysicalPath()), portal_type=['opengever.document.document', 'opengever.task.task', 'ftw.mail.mail']) for obj in objects: obj.getObject().reindexObject(idxs=['containing_subdossier'])
def reindex_containing_dossier(dossier, event): """Reindex the containging_dossier index for all the contained obects, when the title has changed. """ if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return if not IDossierMarker.providedBy(aq_parent(aq_inner(dossier))): attrs = tuple( attr for descr in event.descriptions for attr in descr.attributes ) if 'IOpenGeverBase.title' in attrs: for brain in dossier.portal_catalog(path='/'.join(dossier.getPhysicalPath())): brain.getObject().reindexObject(idxs=['containing_dossier']) if brain.portal_type in ['opengever.task.task', 'opengever.inbox.forwarding']: sync_task(brain.getObject(), event)
def testDeletion(self): from zope.event import subscribers tree = BTreeContainer() item = Contained() tree['42'] = item events = [] def subscriber(event): events.append(event) # events should happen after the deletion, not before) self.assertEqual(len(tree), 0) self.assertEqual(list(tree), []) subscribers.append(subscriber) del tree['42'] self.assertEqual(item.__name__, None) self.assertEqual(item.__parent__, None) self.assertEqual(len(events), 2) self.assertTrue(IObjectRemovedEvent.providedBy(events[0])) self.assertTrue(IContainerModifiedEvent.providedBy(events[1]))
def task_modified(context, event): if IContainerModifiedEvent.providedBy(event): return title = _( u'label_task_modified', default=u'Task modified: ${title}', mapping={'title': context.title_or_id(), }) # XXX dirty try: # if we delete the working copy, # we get a aq_based object and don't wanna # make a journal entry context.portal_types except AttributeError: return journal_entry_factory( context.aq_inner.aq_parent, TASK_MODIIFED_ACTION, title) return
def reindex_contained_objects(dossier, event): """When a subdossier is modified, we update the ``containing_subdossier`` index of all contained objects (documents, mails and tasks) so they don't show an outdated title in the ``subdossier`` column """ if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return catalog = api.portal.get_tool('portal_catalog') parent = aq_parent(aq_inner(dossier)) is_subdossier = IDossierMarker.providedBy(parent) if is_subdossier: objects = catalog(path='/'.join(dossier.getPhysicalPath()), portal_type=[ 'opengever.document.document', 'opengever.task.task', 'ftw.mail.mail' ]) for obj in objects: obj.getObject().reindexObject(idxs=['containing_subdossier'])
def dossier_modified(context, event): if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return title = _( u'label_dossier_modified', default=u'Dossier modified: ${title}', mapping={'title': context.title_or_id(), }) # XXX dirty try: # if we delete the working copy, # we get a aq_based object and don't wanna # make a journal entry context.portal_types except AttributeError: return journal_entry_factory( context, DOSSIER_MODIIFED_ACTION, title, visible=False) return
def reindex_containing_dossier(dossier, event): """Reindex the containging_dossier index for all the contained obects, when the title has changed. """ if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return if not IDossierMarker.providedBy(aq_parent(aq_inner(dossier))): attrs = tuple(attr for descr in event.descriptions for attr in descr.attributes) if 'IOpenGeverBase.title' in attrs: for brain in dossier.portal_catalog( path='/'.join(dossier.getPhysicalPath())): brain.getObject().reindexObject(idxs=['containing_dossier']) if brain.portal_type in [ 'opengever.task.task', 'opengever.inbox.forwarding' ]: sync_task(brain.getObject(), event)
def testDeleteEvents(self): self.assertRaises(KeyError, self.reflecto.manage_delObjects, ('monty',)) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_delObjects, ('foo', 'monty',)) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeRemovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(self.reflecto.manage_delObjects(('foo',)), None) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeRemovedEvent.providedBy(events[1])) self.assertTrue(IObjectRemovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def update_quick_line_styles(context, event=None): # on zope.container.contained.ContainerModifiedEvent, we ignore: if IContainerModifiedEvent.providedBy(event): return quick = context.quick_styles or [] existing = [l for l in context.objectValues() if ILineStyle.providedBy(l)] val = lambda o, name, default: spec.get(name, getattr(o, name, default)) copy_to = lambda o, name, default: setattr(o, name, val(o, name, default)) i = -1 for spec in quick: i += 1 if i + 1 <= len(existing): line_style = existing[i] copy_to(line_style, 'color', 'Auto') copy_to(line_style, 'marker_style', 'square') else: line_style = createContentInContainer(context, LINESTYLE_TYPE, title=u'Line style %s' % (i + 1), **spec)
def reindex_contained_objects(dossier, event): """When a dossier is modified, if the title has changed we reindex the corresponding index in all contained object (containing_dossier or containing_subdossier) """ if ILocalrolesModifiedEvent.providedBy(event) or \ IContainerModifiedEvent.providedBy(event): return attrs = tuple( attr for descr in event.descriptions for attr in descr.attributes ) if 'IOpenGeverBase.title' not in attrs: return if dossier.is_subdossier(): reindex_containing_subdossier_for_contained_objects(dossier, event) else: reindex_containing_dossier_for_contained_objects(dossier, event)
def update_quick_line_styles(context, event=None): # on zope.container.contained.ContainerModifiedEvent, we ignore: if IContainerModifiedEvent.providedBy(event): return quick = context.quick_styles or [] existing = [l for l in context.objectValues() if ILineStyle.providedBy(l)] val = lambda o, name, default: spec.get(name, getattr(o, name, default)) copy_to = lambda o, name, default: setattr(o, name, val(o, name, default)) i = -1 for spec in quick: i += 1 if i + 1 <= len(existing): line_style = existing[i] copy_to(line_style, 'color', 'Auto') copy_to(line_style, 'marker_style', 'square') else: line_style = createContentInContainer( context, LINESTYLE_TYPE, title=u'Line style %s' % (i + 1), **spec )
def testDeleteEvents(self): self.assertRaises(KeyError, self.reflecto.manage_delObjects, ('monty', )) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_delObjects, ( 'foo', 'monty', )) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeRemovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(self.reflecto.manage_delObjects(('foo', )), None) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeRemovedEvent.providedBy(events[1])) self.assertTrue(IObjectRemovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def log_modify(content, event): if not events.IPublishingEvent.providedBy(event): if IContainerModifiedEvent.providedBy(event): LoggingEvent('modify the container', content).log() else: LoggingEvent('modify', content).log()
def set_roles_after_modifying(context, event): if IContainerModifiedEvent.providedBy(event): return LocalRolesSetter(context)(event)
def update_size_usage_for_object(context, event): if IContainerModifiedEvent.providedBy(event): return for size_quota in size_quotas_in_chain_of(context): size_quota.update_object_usage(context)
def _skip(self, obj, event): return IContainerModifiedEvent.providedBy(event)
def onProductCRUD(context, event): # If the event group container was modified by adding a child product, ignore. if IEventGroup.providedBy(context) and IContainerModifiedEvent.providedBy(event): return False # Check if this object is a child product is_child_product = IsChildProduct(context)() # Get the portal_workflow tool wftool = getToolByName(context, "portal_workflow") # Iterate up through the acquisition chain for o in aq_chain(event.object): # Break out if we've made it up to the Plone site. if IPloneSiteRoot.providedBy(o): break # If the item in the aq_chain is a product. # If our parent is a product defined as a product if IAtlasProduct.providedBy(o): try: review_state = wftool.getInfoFor(o, 'review_state').lower() except WorkflowException: review_state = '' # If the object that triggered the event is a child product, just # reindex the item in the chain. if is_child_product: o.reindexObject() # Otherwise, if the product is in a Published state, retract elif review_state in ['published', 'expiring_soon']: # Check if person has reviewer role on context try: is_reviewer = checkPermission('cmf.ReviewPortalContent', o) except NoInteraction: # If we're running this through a script, just assume # we can review. is_reviewer = True # If this person isn't a reviewer, retract it for review. if not is_reviewer: # Comments for transition comments = [] # If we're operating on the product, append a simple comment if o.UID() == event.object.UID(): # Comment explaining why this was retracted comments.append("Automatically retracted due to editing product.") # If we're operating on product content, be more verbose else: # Comment explaining why this was retracted comments.append("Automatically retracted due to editing content inside product.") # Append any change note from page edit to the product edit. comments.append(getChangeNote(event)) comment = ' '.join(comments).strip() # Retract the product wftool.doActionFor(o, 'retract', comment=comment) else: # If the person *is* a reviewer, explicitly set last modified date o.setModificationDate(DateTime()) # Reindex. o.reindexObject() o.reindexObjectSecurity() # Not sure if we need this else: # Regardless, reindex the product so it recalculates the content checks o.reindexObject(idxs=['ContentIssues',]) o.reindexObject(idxs=['ContentErrorCodes']) return True return False
def sync_proposal(obj, event): if IContainerModifiedEvent.providedBy(event): return ProposalSqlSyncer(obj, event).sync()