def containing_subdossier(obj): """Returns the title of the subdossier the object is contained in, unless it's contained directly in the root of a dossier, in which case an empty string is returned. """ if obj.portal_type not in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX: return '' context = aq_inner(obj) parent = context parent_dossier = None parent_dossier_found = False while not parent_dossier_found: parent = aq_parent(parent) if ISiteRoot.providedBy(parent): # Shouldn't happen, just to be safe break if IDossierMarker.providedBy(parent): parent_dossier_found = True parent_dossier = parent if IDossierMarker.providedBy(aq_parent(parent_dossier)): # parent dossier is a subdossier return parent_dossier.Title() return ''
def containing_subdossier(obj): """Returns the title of the subdossier the object is contained in, unless it's contained directly in the root of a dossier, in which case an empty string is returned. """ context = aq_inner(obj) # Only compute for types that actually can be contained in a dossier if not context.portal_type in ['opengever.document.document', 'opengever.task.task', 'ftw.mail.mail']: return '' parent = context parent_dossier = None parent_dossier_found = False while not parent_dossier_found: parent = aq_parent(parent) if ISiteRoot.providedBy(parent): # Shouldn't happen, just to be safe break if IDossierMarker.providedBy(parent): parent_dossier_found = True parent_dossier = parent if IDossierMarker.providedBy(aq_parent(parent_dossier)): # parent dossier is a subdossier return parent_dossier.Title() return ''
def containing_subdossier(obj): """Returns the title of the subdossier the object is contained in, unless it's contained directly in the root of a dossier, in which case an empty string is returned. """ context = aq_inner(obj) # Only compute for types that actually can be contained in a dossier if context.portal_type not in [ 'opengever.document.document', 'opengever.task.task', 'ftw.mail.mail' ]: return '' parent = context parent_dossier = None parent_dossier_found = False while not parent_dossier_found: parent = aq_parent(parent) if ISiteRoot.providedBy(parent): # Shouldn't happen, just to be safe break if IDossierMarker.providedBy(parent): parent_dossier_found = True parent_dossier = parent if IDossierMarker.providedBy(aq_parent(parent_dossier)): # parent dossier is a subdossier return parent_dossier.Title() return ''
def object_moved_or_added(context, event): if isinstance(event, ObjectAddedEvent): # Don't consider moving or removing an object a "touch". Mass-moves # would immediately fill up the touched log, and removals should not # be tracked anyway. if should_track_touches(context): notify(ObjectTouchedEvent(context)) # If an object has been copy & pasted, we need to reindex some fields. # The IObjectCopiedEvent is too early to do that though, because at # that point the object doesn't have a full AQ chain yet. We therefore # just mark it during IObjectCopiedEvent, and do the reindexing here. if getattr(context, '_v_object_has_been_copied', False): context.reindexObject(idxs=reindex_after_copy) if IObjectRemovedEvent.providedBy(event): return # Update object security after moving or copying. # Specifically, this is needed for the case where an object is moved out # of a location where a Placeful Workflow Policy applies to a location # where it doesn't. # # Plone then no longer provides the placeful workflow for that object, # but doesn't automatically update the object's security. # # We use ftw.upgrade's update_security_for() here to correctly # recalculate security, but do the reindexing ourselves because otherwise # Plone will do it recursively (unnecessarily so). changed = update_security_for(context, reindex_security=False) if changed: reindex_object_security_without_children(context) # There are several indices that need updating when a dossier is moved. # first make sure obj was actually moved and not created if not event.oldParent or not event.newParent: return # When an object is moved, its containing_dossier needs reindexing. to_reindex = ['containing_dossier'] # containing_subdossier is really only used for documents, # while is_subdossier is only meaningful for dossiers. if IDossierMarker.providedBy(context): was_subdossier = IDossierMarker.providedBy(event.oldParent) is_subdossier = IDossierMarker.providedBy(event.newParent) if was_subdossier != is_subdossier: to_reindex.append('is_subdossier') if context.portal_type in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX: to_reindex.append('containing_subdossier') context.reindexObject(idxs=to_reindex) # synchronize with model if necessary if ITask.providedBy(context): sync_task(context, event)
def test_one_of_the_parents_of_content_needs_to_be_a_dossier(self): self.login(self.regular_user) self.assertTrue(IDossierMarker.providedBy(aq_parent(self.document))) self.assertTrue(can_access_archival_file_form(self.regular_user, self.document)) self.assertFalse(IDossierMarker.providedBy(aq_parent(self.taskdocument))) self.assertTrue(can_access_archival_file_form(self.regular_user, self.taskdocument)) self.login(self.administrator) self.assertFalse(can_access_archival_file_form(self.administrator, self.inbox_document))
def object_moved_or_added(context, event): if isinstance(event, ObjectAddedEvent): # Don't consider moving or removing an object a "touch". Mass-moves # would immediately fill up the touched log, and removals should not # be tracked anyway. if should_track_touches(context): notify(ObjectTouchedEvent(context)) if IObjectRemovedEvent.providedBy(event): return # Update object security after moving or copying. # Specifically, this is needed for the case where an object is moved out # of a location where a Placeful Workflow Policy applies to a location # where it doesn't. # # Plone then no longer provides the placeful workflow for that object, # but doesn't automatically update the object's security. # # We use ftw.upgrade's update_security_for() here to correctly # recalculate security, but do the reindexing ourselves because otherwise # Plone will do it recursively (unnecessarily so). changed = update_security_for(context, reindex_security=False) if changed: reindex_object_security_without_children(context) # There are several indices that need updating when a dossier is moved. # first make sure obj was actually moved and not created if not event.oldParent or not event.newParent: return # When an object is moved, its containing_dossier needs reindexing. to_reindex = ['containing_dossier'] # containing_subdossier is really only used for documents, # while is_subdossier is only meaningful for dossiers. if IDossierMarker.providedBy(context): was_subdossier = IDossierMarker.providedBy(event.oldParent) is_subdossier = IDossierMarker.providedBy(event.newParent) if was_subdossier != is_subdossier: to_reindex.append('is_subdossier') if context.portal_type in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX: to_reindex.append('containing_subdossier') context.reindexObject(idxs=to_reindex) # synchronize with model if necessary if ITask.providedBy(context): sync_task(context, event)
def __call__(self): searchable = [] # append some other attributes to the searchableText index # reference_number refNumb = getAdapter(self.context, IReferenceNumber) searchable.append(refNumb.get_number()) # sequence_number seqNumb = getUtility(ISequenceNumber) searchable.append(str(seqNumb.get_number(self.context))) # responsible info = getUtility(IContactInformation) dossier = IDossier(self.context) searchable.append(info.describe(dossier.responsible).encode( 'utf-8')) # filling_no dossier = IDossierMarker(self.context) if getattr(dossier, 'filing_no', None): searchable.append(str(getattr(dossier, 'filing_no', None)).encode('utf-8')) # comments comments = getattr(IDossier(self.context), 'comments', None) if comments: searchable.append(comments.encode('utf-8')) return ' '.join(searchable)
def move_repository_reference_mappings(self, obj): intids = getUtility(IIntIds) annotations = IAnnotations(obj) if annotations and annotations.get(CHILD_REF_KEY): repository_mapping = PersistentDict( {CHILD_REF_KEY: {}, PREFIX_REF_KEY: {}}) dossier_mapping = PersistentDict( {CHILD_REF_KEY: {}, PREFIX_REF_KEY: {}}) for number, intid in annotations.get(CHILD_REF_KEY).items(): try: child = intids.getObject(intid) except KeyError: # the object with this intid does not longer exist. continue if IDossierMarker.providedBy(child): dossier_mapping[CHILD_REF_KEY][number] = intid dossier_mapping[PREFIX_REF_KEY][intid] = number else: repository_mapping[CHILD_REF_KEY][number] = intid repository_mapping[PREFIX_REF_KEY][intid] = number # save mapping annotations[REPOSITORY_FOLDER_KEY] = repository_mapping annotations[DOSSIER_KEY] = dossier_mapping # drop old mapings annotations.pop(CHILD_REF_KEY) annotations.pop(PREFIX_REF_KEY)
def _construct_object(self, container, item): portal_type = item['_type'] fti = self._get_fti(portal_type) title_args = self._get_title_args(fti, item) with NoDossierReferenceNumbersIssued(): # Create the object without automatically issuing a # reference number - we might want to set it explicitly obj = createContentInContainer( container, portal_type, **title_args) if IDossierMarker.providedBy(obj): prefix_adapter = IReferenceNumberPrefix(container) if not prefix_adapter.get_number(obj): # Set the local reference number part for the # dossier if provided in item, otherwise have # the adapter issue the next one local_refnum = item.get('reference_number') if local_refnum is not None: prefix_adapter.set_number(obj, local_refnum) else: prefix_adapter.set_number(obj) self._set_guid(obj, item) return obj
def is_locked(self, recursive=True): """Determine whether a dossier currently is resolve locked. By default also considers a subdossier locked if any of its parent dossiers have a lock on them. If recursive=False is given, only the current dossier is checked for a lock (cheaper, this is used to display the state in the byline). If a lock exists (somewhere) but is older than RESOLVE_LOCK_LIFETIME, it is considered expired and treated as if it wouldn't exist. """ item = self.context while IDossierMarker.providedBy(item): lockinfo = self.get_lockinfo(item) if lockinfo is not None and not self.is_expired(lockinfo): self.log("%s is resolve locked via lock on %r" % (self.context, item)) return True if not recursive: return False item = aq_parent(item) return False
def raise_invalid(self): if IDossierMarker.providedBy(self.context): mail_address = IEmailAddress( self.request).get_email_for_object(self.context) else: parent = aq_parent(aq_inner(self.context)) mail_address = IEmailAddress( self.request).get_email_for_object(parent) # Remove widget value in order to disable that the widget renders # radio-buttons (nochange/remove/replace) once a file has been # uploaded. # This is a special case since we are an additional validator # for the file field that may block an otherwise valid file upload. # The widget does not expect this to happen though. if getattr(self.view.parentForm, '_nullify_file_on_error', False): self.widget.value = None raise Invalid(_( u'error_mail_upload', default=(u"It's not possible to add E-mails here, please " "send it to ${mailaddress} or drag it to the dossier " "(Dragn'n'Drop)."), mapping={'mailaddress': mail_address} ))
def get_containing_dossier(obj): while not IPloneSiteRoot.providedBy(obj): if IDossierMarker.providedBy(obj) or IInbox.providedBy(obj): return obj obj = aq_parent(aq_inner(obj)) return None
def render(self): self.request.response.setHeader('Content-type', 'application/json') payloads = self.get_base_payloads() dossier_notifications = {} for payload in payloads: document = payload['document'] parent_dossier = document.get_parent_dossier() if (parent_dossier and IDossierMarker.providedBy(parent_dossier)): if parent_dossier.is_open(): payload['bcc'] = (IEmailAddress( self.request).get_email_for_object(parent_dossier)) parent_dossier_uuid = api.content.get_uuid(parent_dossier) if parent_dossier_uuid not in dossier_notifications: dossier_notifications[parent_dossier_uuid] = [] dossier_notifications[parent_dossier_uuid].append(document) payload['title'] = document.title_or_id() payload['content-type'] = document.get_file().contentType payload['download'] = document.get_download_view_name() payload['filename'] = document.get_filename() del payload['document'] notify(FileAttachedToEmailEvent(document)) for uuid, documents in dossier_notifications.iteritems(): dossier = api.content.get(UID=uuid) notify(DossierAttachedToEmailEvent(dossier, documents)) return json.dumps(payloads)
def _add_descendants(self): objs = self.obj.objectValues() for obj in objs: if IDossierMarker.providedBy(obj): self.dossiers.append(Dossier(obj, self.path)) elif IBaseDocument.providedBy(obj) and obj.get_file(): self.documents.append(Document(obj, self.path))
def isSubdossierIndexer(obj): # TODO: should be replaced with the is_subdossier method # from og.dossier.base.py parent = aq_parent(aq_inner(obj)) if IDossierMarker.providedBy(parent): return True return False
def is_allowed(self): """Perform the necessary checks to determine whether pasting is allowed / possible on the current context. """ # Check whether pasting is allowed at all for the container type if self.context.portal_type in self.disabled_types: return False # XXX implement me in a more object oriented manner, i.e. by # implementing `is_pasting_allowed` for all our content types. if IDossierMarker.providedBy(self.context): if not self.context.is_open(): return False objs = Clipboard(self.request).get_objs() if not objs: # Clipboard empty return False # Check whether there's an object in the clipboard whose type # is not allowed to be added to the container for obj in objs: if obj.portal_type not in self.allowed_content_types: return False return self.validate_private_folder_pasting(objs)
def get_redirect_url(context): """return the url where the editing_document view was called from It should be a document listing.""" referer = context.REQUEST.environ.get('HTTP_REFERER') portal_url = '/'.join(context.portal_url().split('/')[:-1]) if referer: obj_path = referer[len(portal_url):] try: obj = context.restrictedTraverse(obj_path) except KeyError: return '%s#overview' % context.absolute_url() # redirect to right tabbedview-tab if ITask.providedBy(obj): return '%s#relateddocuments' % (obj.absolute_url()) elif IPloneSiteRoot.providedBy(obj): return '%s#mydocuments' % (obj.absolute_url()) elif IDossierMarker.providedBy(obj): return '%s#documents' % (obj.absolute_url()) else: return obj.absolute_url() else: return '%s#overview' % context.absolute_url()
def replace_interactive_user(self, principal): """Replaces interactive users in the principal. """ if principal == 'responsible': # find the dossier dossier = self.context while not IDossierMarker.providedBy(dossier): if IPloneSiteRoot.providedBy(dossier): raise ValueError('Could not find dossier') dossier = aq_parent(aq_inner(dossier)) # get the responsible of the dossier wrapped_dossier = IDossier(dossier) return wrapped_dossier.responsible elif principal == 'current_user': # get the current user mtool = getToolByName(self.context, 'portal_membership') member = mtool.getAuthenticatedMember() if not member: raise Unauthorized() return member.getId() else: return principal
def get_parent_dossier(self): parent = aq_parent(aq_inner(self)) if IDossierMarker.providedBy(parent): return parent return None
def is_allowed(self): """Perform the necessary checks to determine whether pasting is allowed / possible on the current context. """ # Check whether the user has Copy or Move on the context if not api.user.has_permission('Copy or Move', obj=self.context): return False # Check whether pasting is allowed at all for the container type if self.context.portal_type in self.disabled_types: return False # XXX implement me in a more object oriented manner, i.e. by # implementing `is_pasting_allowed` for all our content types. if IDossierMarker.providedBy(self.context): if not self.context.is_open(): return False objs = Clipboard(self.request).get_objs() if not objs: # Clipboard empty return False # Check whether there's an object in the clipboard whose type # is not allowed to be added to the container for obj in objs: if obj.portal_type not in self.allowed_content_types: return False return self.validate_private_folder_pasting(objs)
def check_dossier_nesting(portal, options): """Find all Dossiers that are nested 3 levels or more (sub-sub-dossiers). """ catalog = getToolByName(portal, 'portal_catalog') dossiers = catalog(object_provides=IDossierMarker.__identifier__) for brain in dossiers: obj = brain.getObject() subdossiers = [c for c in obj.getChildNodes() if IDossierMarker.providedBy(c)] for subdossier in subdossiers: if subdossier.get_subdossiers() != []: badly_nested_dossiers = [c for c in subdossier.getChildNodes() if IDossierMarker.providedBy(c)] print badly_nested_dossiers
def _construct_object(self, container, item): portal_type = item['_type'] fti = self._get_fti(portal_type) title_args = self._get_title_args(fti, item) with NoDossierReferenceNumbersIssued(): # Create the object without automatically issuing a # reference number - we might want to set it explicitly obj = createContentInContainer(container, portal_type, **title_args) if IDossierMarker.providedBy(obj): prefix_adapter = IReferenceNumberPrefix(container) if not prefix_adapter.get_number(obj): # Set the local reference number part for the # dossier if provided in item, otherwise have # the adapter issue the next one local_refnum = item.get('reference_number') if local_refnum is not None: prefix_adapter.set_number(obj, local_refnum) else: prefix_adapter.set_number(obj) self._set_guid(obj, item) return obj
def _add_descendants(self): objs = self.obj.objectValues() for obj in objs: if IDossierMarker.providedBy(obj): self.dossiers[obj.UID()] = Dossier(obj) elif IDocumentSchema.providedBy(obj): self.documents[obj.UID()] = Document(obj)
def allowedContentTypes(self, *args, **kwargs): types = super( DossierContainer, self).allowedContentTypes(*args, **kwargs) # calculate depth depth = 0 obj = self while IDossierMarker.providedBy(obj): depth += 1 obj = aq_parent(aq_inner(obj)) if IPloneSiteRoot.providedBy(obj): break # the adapter decides def filter_type(fti): # first we try the more specific one ... decider = queryMultiAdapter((self.REQUEST, self, fti), IConstrainTypeDecider, name=fti.portal_type) if not decider: # .. then we try the more general one decider = queryMultiAdapter((self.REQUEST, self, fti), IConstrainTypeDecider) if decider: return decider.addable(depth) # if we don't have an adapter, we just allow it return True # filter return filter(filter_type, types)
def allowedContentTypes(self, *args, **kwargs): types = super(DossierContainer, self).allowedContentTypes(*args, **kwargs) # calculate depth depth = 0 obj = self while IDossierMarker.providedBy(obj): depth += 1 obj = aq_parent(aq_inner(obj)) if IPloneSiteRoot.providedBy(obj): break # the adapter decides def filter_type(fti): # first we try the more specific one ... decider = queryMultiAdapter((self.REQUEST, self, fti), IConstrainTypeDecider, name=fti.portal_type) if not decider: # .. then we try the more general one decider = queryMultiAdapter((self.REQUEST, self, fti), IConstrainTypeDecider) if decider: return decider.addable(depth) # if we don't have an adapter, we just allow it return True # filter return filter(filter_type, types)
def test_one_of_the_parents_of_content_needs_to_be_a_dossier(self): self.login(self.regular_user) self.assertTrue(IDossierMarker.providedBy(aq_parent(self.document))) self.assertTrue( can_access_archival_file_form(self.regular_user, self.document)) self.assertFalse( IDossierMarker.providedBy(aq_parent(self.taskdocument))) self.assertTrue( can_access_archival_file_form(self.regular_user, self.taskdocument)) self.login(self.administrator) self.assertFalse( can_access_archival_file_form(self.administrator, self.inbox_document))
def test_create_dossier_from_template(self): self.login(self.regular_user) command = CreateDossierFromTemplateCommand(self.dossier, self.dossiertemplate) dossier = command.execute() self.assertEqual(self.dossiertemplate.title, dossier.title) self.assertTrue(IDossierMarker.providedBy(dossier))
def render(self): self.request.response.setHeader('Content-type', 'application/json') payloads = self.get_base_payloads() dossier_notifications = {} for payload in payloads: document = payload['document'] parent_dossier = document.get_parent_dossier() if parent_dossier and IDossierMarker.providedBy(parent_dossier) and parent_dossier.is_open(): payload['bcc'] = IEmailAddress(self.request).get_email_for_object(parent_dossier) parent_dossier_uuid = api.content.get_uuid(parent_dossier) if parent_dossier_uuid not in dossier_notifications: dossier_notifications[parent_dossier_uuid] = [] dossier_notifications[parent_dossier_uuid].append(document) payload['title'] = document.title_or_id() payload['content-type'] = document.get_file().contentType payload['download'] = document.get_download_view_name() payload['filename'] = document.get_filename() del payload['document'] notify(FileAttachedToEmailEvent(document)) for uuid, documents in dossier_notifications.iteritems(): dossier = api.content.get(UID=uuid) notify(DossierAttachedToEmailEvent(dossier, documents)) return json.dumps(payloads)
def _add_descendants(self): objs = self.obj.objectValues() for obj in objs: if IDossierMarker.providedBy(obj): self.dossiers.append(Dossier(obj, self.path)) elif IDocumentSchema.providedBy(obj): self.documents.append(Document(obj, self.path))
def label(self): if IDossierMarker.providedBy(self.context): return _(u'Add Subdossier') else: portal_type = self.portal_type fti = getUtility(IDexterityFTI, name=portal_type) type_name = fti.Title() return pd_mf(u"Add ${name}", mapping={'name': type_name})
def get_contained_folders(folder): children = folder.getChildNodes() return [ child for child in children if IDossierMarker.providedBy(child) if api.user.has_permission('View', obj=child) ]
def assert_valid_container_state(self): container = self.context if not self.within_template_folder(container) and \ IDossierMarker.providedBy(container) and not container.is_open(): msg = _(u'Can only move objects from open dossiers!') IStatusMessage(self.request).addStatusMessage(msg, type='error') self.request.RESPONSE.redirect('%s#documents' % container.absolute_url())
def assert_valid_container_state(self): container = self.context if IDossierMarker.providedBy(container) and not container.is_open(): msg = _(u'Can only move objects from open dossiers!') IStatusMessage(self.request).addStatusMessage( msg, type='error') self.request.RESPONSE.redirect( '%s#documents' % container.absolute_url())
def default_title(context): # At this point, only proposals (not submitted proposals) should acquire # an actual default. This is indicated by the parent being a dossier. if not IDossierMarker.providedBy(context): return u'' # Use Title() accessor to make this defaultFactor robust in regard to # objects with ITranslatedTitle behavior or titles stored in SQL return context.Title().decode('utf-8')
def top_dossier_title(obj): """return the tilte of the top containing dossier.""" dossier_title = '' while not IPloneSiteRoot.providedBy(obj): if IDossierMarker.providedBy( obj) or obj.portal_type == 'opengever.inbox.inbox': dossier_title = obj.Title() obj = aq_parent(aq_inner(obj)) return dossier_title
def handle_submit(self, action): data, errors = self.extractData() if len(errors) == 0: source = data['request_paths'].split(';;') destination = data['destination_folder'] failed_objects = [] failed_resource_locked_objects = [] copied_items = 0 for path in source: # Get source object src_object = self.context.unrestrictedTraverse( path.encode('utf-8')) # Get parent object source_container = aq_parent(aq_inner( self.context.unrestrictedTraverse( path.encode('utf-8')))) src_name = src_object.title src_id = src_object.id # If parent isn't a dossier and obj is a document # it's connected to a task and shouldn't be moved if not IDossierMarker.providedBy(source_container) and \ IDocumentSchema.providedBy(src_object): msg = _(u'Document ${name} is connected to a Task.\ Please move the Task.', mapping=dict(name=src_name)) IStatusMessage(self.request).addStatusMessage( msg, type='error') continue try: # Try to cut and paste object clipboard = source_container.manage_cutObjects(src_id) destination.manage_pasteObjects(clipboard) copied_items += 1 except ResourceLockedError: # The object is locket over webdav failed_resource_locked_objects.append(src_name) continue except (ValueError, CopyError): # Catch exception and add title to a list of failed objects failed_objects.append(src_name) continue self.create_statusmessages( copied_items, failed_objects, failed_resource_locked_objects, ) self.request.RESPONSE.redirect(destination.absolute_url())
def find_dossier(self): obj = self.context while not IPloneSiteRoot.providedBy(obj): if IDossierMarker.providedBy(obj): return obj else: obj = aq_parent(aq_inner(obj)) return None
def available(self): if not self.enabled(): return False if IDossierMarker.providedBy(self.context): return True if not IRepositoryFolder.providedBy(self.context): return False if self.context.is_leaf_node(): return True return False
def _get_dossier_depth(self): # calculate depth depth = 0 obj = self while IDossierMarker.providedBy(obj): depth += 1 obj = aq_parent(aq_inner(obj)) if IPloneSiteRoot.providedBy(obj): break return depth
def containing_subdossier_title(self): """"Returns the title of the subdossier which the document is placed in. Returns None when the object is placed directly inside a main dossier. """ dossier = self.get_parent_dossier() # Return None if the dossier is a main dossier if not IDossierMarker.providedBy(aq_parent(dossier)): return None return dossier.title
def find_parent_dossier(content): """Returns the first parent dossier relative to the current context. """ if IPloneSiteRoot.providedBy(content): raise ValueError('Site root passed as argument.') while content and not IDossierMarker.providedBy(content): content = aq_parent(aq_inner(content)) if IPloneSiteRoot.providedBy(content): raise ValueError('Site root reached while searching ' 'parent dossier.') return content
def get_main_dossier(obj): """Helper method which returns the main dossier (or inbox) of the given object. If the given object is not storred inside a dossier it returns None.""" dossier = None while not IPloneSiteRoot.providedBy(obj): if IDossierMarker.providedBy(obj) or IInbox.providedBy(obj): dossier = obj obj = aq_parent(aq_inner(obj)) return dossier
def find_parent_dossier(self): """Returns the first parent dossier relative to the current context. """ obj = self.context while not IDossierMarker.providedBy(obj): obj = aq_parent(aq_inner(obj)) if IPloneSiteRoot.providedBy(obj): return ValueError('Site root reached while searching ' 'parent dossier.') return obj
def reindex_containing_dossier(dossier, event): """Reindex the containging_dossier index for all the contained obects, when the title has changed.""" if not IDossierMarker.providedBy(aq_parent(aq_inner(dossier))): for descr in event.descriptions: for attr in descr.attributes: if attr == "IOpenGeverBase.title": 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)