Пример #1
0
def modifiedCoverTile(obj, event):
    """Ensure link integrity on Rich Text tiles.

    Keyword arguments:
    obj -- Dexterity-based object that was modified
    event -- event fired
    """
    pu = api.portal.get_tool('portal_url')
    if pu is None:
        # `getObjectFromLinks` is not possible without access
        # to `portal_url`
        return
    rc = api.portal.get_tool('reference_catalog')
    if rc is None:
        # `updateReferences` is not possible without access
        # to `reference_catalog`
        return
    referenceable_parent = IReferenceable(obj.context, None)
    if referenceable_parent is None:
        # `updateReferences` is not possible
        # if parent object isn't referenceable
        return

    refs = set()

    for name, value in obj.data.items():
        if isinstance(value, RichTextValue):
            value = value.raw
            if not value:
                continue
            links = extractLinks(value)
            refs |= getObjectsFromLinks(obj.context, links)

    updateReferences(IReferenceable(obj.context), referencedRelationship, refs)
Пример #2
0
def getObjectsFromLinks(base, links):
    """ determine actual objects refered to by given links """
    objects = set()
    url = base.absolute_url()
    scheme, host, path, query, frag = urlsplit(url)
    for link in links:
        s, h, path, q, f = urlsplit(link)
        # relative or local url
        if (not s and not h) or (s == scheme and h == host):
            # Paths should always be strings
            if isinstance(path, unicode):
                path = path.encode('utf-8')

            obj, extra = findObject(base, path)
            if obj:
                if IOFSImage.providedBy(obj):
                    # use atimage object for scaled images
                    obj = aq_parent(obj)
                if not IReferenceable.providedBy(obj):
                    try:
                        obj = IReferenceable(obj)
                    except:
                        continue
                objects.add(obj)
    return objects
Пример #3
0
    def test_circular_reference_subfolder_deletion(self):
        doc1 = self.portal.doc1
        doc2 = self.portal.doc2
        doc4 = self.portal.folder1.doc4

        # This tests the behaviour when removing three object
        # referencing each other in a circle.  This situation cannot be
        # resolved completely, since the removal events are fired
        # separately.  However, the circle gets "broken up" when
        # confirming the removal of the first object, and no further
        # confirmation form are necessary:
        self._set_text(doc1, '<a href="doc2">documents...</a>')
        self._set_text(doc2, '<a href="folder1/doc4">linking...</a>')
        self._set_text(doc4, '<a href="../doc1">in circles.</a>')
        self.assertEqual(IReferenceable(doc1).getReferences(), [doc2, ])
        self.assertEqual(IReferenceable(doc2).getReferences(), [doc4, ])
        self.assertEqual(IReferenceable(doc4).getReferences(), [doc1, ])

        self.assertRaises(exceptions.LinkIntegrityNotificationException,
            self.portal.manage_delObjects, ['doc1', 'doc2', ], self.request)
        transaction.abort()

        self.portal.manage_delObjects(
            ['doc1', 'doc2', 'folder1', ], self.request)

        self.assertNotIn('doc1', self.portal)
        self.assertNotIn('doc2', self.portal)
        self.assertNotIn('folder1', self.portal)
Пример #4
0
def moved_handler(obj, event):
    """Remove object from uid_catalog and add it back"""
    # Not sure if this is the proper way to handle it.
    # it is needed because of what happens in Products.ZCatalog.Catalog.py
    # line 317.
    # When path has changed, the object cannot be found, and we end up with
    # old and invalid uids.
    uid_catalog, ref_catalog = _get_catalogs(obj)
    uid = IUUID(obj.aq_base, None)

    if uid:
        results = uid_catalog(UID=uid)

        if len(results) > 0:
            old_obj = results[0]
            uid_catalog.uncatalog_object(old_obj.getPath())
            path = '/'.join(obj.getPhysicalPath())
            uid_catalog.catalog_object(obj, path)

    #  AT API
    annotations = IATReferenceable(obj)._getReferenceAnnotations()
    if not annotations:
        return

    for ref in annotations.objectValues():
        url = getRelURL(ref_catalog, ref.getPhysicalPath())
        if event.oldName and event.newName:
            url = event.oldName + url[len(event.newName):]
        uid_catalog_rid = uid_catalog.getrid(url)
        ref_catalog_rid = ref_catalog.getrid(url)
        if uid_catalog_rid is not None:
            uid_catalog.uncatalog_object(url)
        if ref_catalog_rid is not None:
            ref_catalog.uncatalog_object(url)
Пример #5
0
    def test_image_scale_reference_creation(self):
        doc1 = self.portal.doc1
        img1 = self.portal.image1

        # Linking image scales should also work:
        self._set_text(doc1,
                       '<a href="image1/@@images/image_thumb">an image</a>')
        self.assertEqual(IReferenceable(doc1).getReferences(), [img1])
        self.assertEqual(IReferenceable(img1).getBackReferences(), [doc1])
Пример #6
0
 def working_copy(self):
     adapted = IReferenceable(self.context, None)
     if adapted is None:
         return None
     refs = adapted.getBRefs(WorkingCopyRelation.relationship)
     if len(refs) > 0:
         return refs[0]
     else:
         return None
Пример #7
0
    def test_image_resolveuid_reference_creation(self):
        doc1 = self.portal.doc1
        img1 = self.portal.image1

        # Linking via the "resolveuid/UID" method should also work:
        self._set_text(
            doc1,
            '<a href="resolveuid/{0:s}">an image</a>'.format(IUUID(img1)))

        self.assertEqual(IReferenceable(doc1).getReferences(), [img1])
        self.assertEqual(IReferenceable(img1).getBackReferences(), [doc1])
Пример #8
0
    def test_image_tag_reference_creation(self):
        doc1 = self.portal.doc1
        img1 = self.portal.image1

        # This tests the correct creation of references used for
        # ensuring link integrity. Any archetype-based content object
        # which refers to other (local) objects by `<img>` or `<a>` tags
        # should create references between those objects on save.
        self._set_text(doc1, img1.restrictedTraverse('@@images').tag())

        self.assertEqual(IReferenceable(doc1).getReferences(), [img1])
        self.assertEqual(IReferenceable(doc1).getBackReferences(), [])
        self.assertEqual(IReferenceable(img1).getReferences(), [])
        self.assertEqual(IReferenceable(img1).getBackReferences(), [doc1])
Пример #9
0
    def get_references(self):
        """ AT references
        """
        try:
            from Products.Archetypes.interfaces import IReferenceable
            if not IReferenceable.providedBy(self.context):
                return
        except:
            return

        self['_atrefs'] = {}
        self['_atbrefs'] = {}
        relationships = self.context.getRelationships()
        for rel in relationships:
            self['_atrefs'][rel] = []
            refs = self.context.getRefs(relationship=rel)
            for ref in refs:
                if ref is not None:
                    self['_atrefs'][rel].append('/'.join(
                        ref.getPhysicalPath()))
        brelationships = self.context.getBRelationships()
        for brel in brelationships:
            self['_atbrefs'][brel] = []
            brefs = self.context.getBRefs(relationship=brel)
            for bref in brefs:
                if bref is not None:
                    self['_atbrefs'][brel].append('/'.join(
                        bref.getPhysicalPath()))
Пример #10
0
def update_links(event):
    obj = event.object
    if is_outdated(obj) or not is_publically_visible(obj):
        return
    temporary = hasattr(obj, 'meta_type') and \
        obj.meta_type == TempFolder.meta_type
    if temporary:
        # Objects that are temporary (read: portal_factory) and do not have a
        # (stable) URL (yet) do not need to be crawled: relative links will be
        # off quickly and we can't really use the UID anyway.
        return
    try:
        link_checker = getToolByName(obj, 'portal_linkchecker').aq_inner
    except AttributeError:
        return
    if not link_checker.active:
        return
    retriever = IRetriever(obj, None)
    if retriever is not None:
        sm = getSecurityManager()
        if not sm.checkPermission(ModifyPortalContent, obj):
            return
        if (not IReferenceable.providedBy(obj)):
            return
        async = getUtility(IAsyncService)
        tpath = '/'.join(obj.getPhysicalPath())
        job = async .queueJob(retrieve_async, obj, tpath, online=True)
        callback = job.addCallbacks(failure=job_failure_callback)
        callback  # for pep
Пример #11
0
    def _notifyOfCopyTo(self, container, op=0):
        """In the case of a move (op=1) we need to make sure
        references are mainained for all referencable objects within
        the one being moved.

        manage_renameObject calls _notifyOfCopyTo so that the
        object being renamed doesn't lose its references. But
        manage_renameObject calls _delObject which calls
        manage_beforeDelete on all the children of the object
        being renamed which deletes all references for children
        of the object being renamed. Here is a patch that does
        recursive calls for _notifyOfCopyTo to address that
        problem.
        """
        # XXX this doesn't appear to be necessary anymore, if it is
        # it needs to be used in BaseBTreeFolder as well, it currently
        # is not.
        BaseObject._notifyOfCopyTo(self, container, op=op)
        # keep reference info internally when op == 1 (move)
        # because in those cases we need to keep refs
        if op==1:
            self._v_cp_refs = 1
        for child in self.contentValues():
            if IReferenceable.providedBy(child):
                child._notifyOfCopyTo(self, op)
Пример #12
0
    def _notifyOfCopyTo(self, container, op=0):
        """In the case of a move (op=1) we need to make sure
        references are mainained for all referencable objects within
        the one being moved.

        manage_renameObject calls _notifyOfCopyTo so that the
        object being renamed doesn't lose its references. But
        manage_renameObject calls _delObject which calls
        manage_beforeDelete on all the children of the object
        being renamed which deletes all references for children
        of the object being renamed. Here is a patch that does
        recursive calls for _notifyOfCopyTo to address that
        problem.
        """
        # XXX this doesn't appear to be necessary anymore, if it is
        # it needs to be used in BaseBTreeFolder as well, it currently
        # is not.
        BaseObject._notifyOfCopyTo(self, container, op=op)
        # keep reference info internally when op == 1 (move)
        # because in those cases we need to keep refs
        if op == 1:
            self._v_cp_refs = 1
        for child in self.contentValues():
            if IReferenceable.providedBy(child):
                child._notifyOfCopyTo(self, op)
    def transmogrify(self, item):
        path = self.get_path(item)
        obj = self.get_object(item)

        uid = item.get(self.uidkey, "")
        if not uid:
            raise NothingToDoHere

        at_uid = ATIReferenceable.providedBy(obj)
        dx_uid = DXIReferenceable.providedBy(obj)

        old_uid = obj.UID()
        if old_uid != uid:
            # Code from plone.app.transmogrifier used for AT objects:
            if at_uid:
                if not old_uid:
                    setattr(obj, AT_UUID_ATTR, uid)
                else:
                    obj._setUID(uid)
            elif dx_uid:
                setattr(obj, DX_UID_ATTR, uid)
            else: #Don't ask, JUST DO IT!
                  # If the attribute is not used as UID, it
                  # is not used as anything else as well,
                  # and at least the desired UID value stays recorded in the
                  # object, allowing for a post-migration retrieval
                setattr(obj, DEFAULT_UID_ATTR, uid)
        return item
Пример #14
0
def modified_handler(obj, event):
    """Reindex object in uid_catalog"""
    uid_catalog, ref_catalog = _get_catalogs(obj)
    path = '/'.join(obj.getPhysicalPath())
    uid_catalog.catalog_object(obj, path)

    #  AT API
    annotations = IATReferenceable(obj)._getReferenceAnnotations()
    if not annotations:
        return

    for ref in annotations.objectValues():
        url = getRelURL(ref_catalog, ref.getPhysicalPath())
        uid_catalog.catalog_object(ref, url)
        ref_catalog.catalog_object(ref, url)
        ref._catalogRefs(uid_catalog, uid_catalog, ref_catalog)
Пример #15
0
def getObjectsFromLinks(base, links):
    """ determine actual objects refered to by given links """
    objects = set()
    url = base.absolute_url()
    scheme, host, path, query, frag = urlsplit(url)
    for link in links:
        s, h, path, q, f = urlsplit(link)
        # relative or local url
        if (not s and not h) or (s == scheme and h == host):
            # Paths should always be strings
            if isinstance(path, unicode):
                path = path.encode('utf-8')

            obj, extra = findObject(base, path)
            if obj:
                if IOFSImage.providedBy(obj):
                    # use atimage object for scaled images
                    obj = aq_parent(obj)
                if not IReferenceable.providedBy(obj):
                    try:
                        obj = IReferenceable(obj)
                    except:
                        continue
                objects.add(obj)
    return objects
Пример #16
0
    def test_removal_via_zmi(self):
        doc1 = self.portal.doc1
        doc2 = self.portal.doc2

        # This tests ensuring link integrity when removing an object via
        # the ZMI.
        self._set_text(doc1, '<a href="doc2">a document</a>')
        self.assertEqual(IReferenceable(doc1).getReferences(), [doc2])

        transaction.commit()
        # Then we use a browser to try to delete the referenced
        # document. Before we can do this we need to prevent the test
        # framework from choking on the exception we intentionally throw.
        self.browser.handleErrors = True

        self.browser.open('http://nohost/plone/manage_main')
        self.browser\
            .getControl(name='ids:list')\
            .getControl(value='doc2').selected = True

        self.browser.getControl('Delete').click()
        self.assertIn('Potential link breakage', self.browser.contents)
        self.assertIn('<a href="http://nohost/plone/doc1">Test Page 1</a>',
                      self.browser.contents)

        # After we have acknowledged the breach in link integrity the
        # document should have been deleted:
        self.browser.getControl(name='delete').click()
        self.assertNotIn('doc2', self.portal.objectIds())
Пример #17
0
    def checkout_allowed(self):
        """Check if a checkout is allowed.
        """
        context = aq_inner(self.context)
        checkPermission = getSecurityManager().checkPermission
        
        if not interfaces.IIterateAware.providedBy(context):
            return False
        
        if not IReferenceable.providedBy(context):
            return False

        archiver = interfaces.IObjectArchiver(context)
        if not archiver.isVersionable():
            return False

        # check if there is an existing checkout
        if len(context.getBRefs(WorkingCopyRelation.relationship)) > 0:
            return False
        
        # check if it is a checkout or contains a checkout
        if recursivelyCheckForWorkingCopies(context):
            return False

        # check if it is contained by a checkout
        if recursivelyCheckParentsForWorkingCopies(context):
            return False

        # check the permission
        if not checkPermission(permissions.CheckoutPermission, context):
            return False
        
        return True
Пример #18
0
    def transmogrify(self, item):
        path = self.get_path(item)
        obj = self.get_object(item)

        uid = item.get(self.uidkey, "")
        if not uid:
            raise NothingToDoHere

        at_uid = ATIReferenceable.providedBy(obj)
        dx_uid = DXIReferenceable.providedBy(obj)

        old_uid = obj.UID()
        if old_uid != uid:
            # Code from plone.app.transmogrifier used for AT objects:
            if at_uid:
                if not old_uid:
                    setattr(obj, AT_UUID_ATTR, uid)
                else:
                    obj._setUID(uid)
            elif dx_uid:
                setattr(obj, DX_UID_ATTR, uid)
            else:  #Don't ask, JUST DO IT!
                # If the attribute is not used as UID, it
                # is not used as anything else as well,
                # and at least the desired UID value stays recorded in the
                # object, allowing for a post-migration retrieval
                setattr(obj, DEFAULT_UID_ATTR, uid)
        return item
Пример #19
0
    def test_files_with_spaces_removal(self):
        doc1 = self.portal.doc1

        # This tests the behaviour when removing a referenced file that has
        # spaces in its id.  First we need to rename the existing file:
        self.portal.invokeFactory('Document',
                                  id='some spaces.doc',
                                  title='A spaces doc')

        self.assertIn('some spaces.doc', self.portal.objectIds())
        spaces1 = self.portal['some spaces.doc']

        self._set_text(doc1, '<a href="some spaces.doc">a document</a>')

        # The document should now have a reference to the file:
        self.assertEqual(IReferenceable(doc1).getReferences(), [spaces1])
        transaction.commit()

        # Then we use a browser to try to delete the referenced file.
        # Before we can do this we need to prevent the test framework
        # from choking on the exception we intentionally throw.
        self.browser.handleErrors = True

        self.browser.open('{0:s}/object_delete?_authenticator={1:s}'.format(
            spaces1.absolute_url(), self._get_token(spaces1)))
        self.assertIn('Potential link breakage', self.browser.contents)
        self.assertIn('<a href="http://nohost/plone/doc1">Test Page 1</a>',
                      self.browser.contents)
        self.browser.getControl(name='delete').click()
        self.assertNotIn('some spaces.doc', self.portal.objectIds())
Пример #20
0
    def __iter__(self):

        for item in self.previous:

            pathkey = self.pathkey(*item.keys())[0]
            uidkey = self.uidkey(*item.keys())[0]

            if not pathkey or not uidkey:  # not enough info
                yield item
                continue

            path = item[pathkey]
            uid = item[uidkey]

            obj = traverse(self.context, str(path).lstrip('/'), None)
            if obj is None:  # path doesn't exist
                yield item
                continue

            if IReferenceable.providedBy(obj):
                oldUID = obj.UID()
                if oldUID != uid:
                    if not oldUID:
                        setattr(obj, UUID_ATTR, uid)
                    else:
                        obj._setUID(uid)

            if IAttributeUUID.providedBy(obj):
                IMutableUUID(obj).set(uid)

            yield item
Пример #21
0
def modifiedDexterity(obj, event):
    """ a dexterity based object was modified """
    pu = getToolByName(obj, 'portal_url', None)
    if pu is None:
        # `getObjectFromLinks` is not possible without access
        # to `portal_url`
        return
    rc = getToolByName(obj, 'reference_catalog', None)
    if rc is None:
        # `updateReferences` is not possible without access
        # to `reference_catalog`
        return

    fti = getUtility(IDexterityFTI, name=obj.portal_type)
    schema = fti.lookupSchema()
    additional_schema = getAdditionalSchemata(context=obj,
                                              portal_type=obj.portal_type)

    schemas = [i for i in additional_schema] + [schema]

    refs = set()

    for schema in schemas:
        for name, field in getFieldsInOrder(schema):
            if isinstance(field, RichText):
                # Only check for "RichText" ?
                value = getattr(schema(obj), name)
                if not value:
                    continue
                links = extractLinks(value.raw)
                refs |= getObjectsFromLinks(obj, links)

    updateReferences(IReferenceable(obj), referencedRelationship, refs)
Пример #22
0
def update_links(event):
    obj = event.object
    if is_outdated(obj) or not is_publically_visible(obj):
        return
    temporary = hasattr(obj, 'meta_type') and \
        obj.meta_type == TempFolder.meta_type
    if temporary:
        # Objects that are temporary (read: portal_factory) and do not have a
        # (stable) URL (yet) do not need to be crawled: relative links will be
        # off quickly and we can't really use the UID anyway.
        return
    try:
        link_checker = getToolByName(obj, 'portal_linkchecker').aq_inner
    except AttributeError:
        return
    if not link_checker.active:
        return
    retriever = IRetriever(obj, None)
    if retriever is not None:
        sm = getSecurityManager()
        if not sm.checkPermission(ModifyPortalContent, obj):
            return
        if (not IReferenceable.providedBy(obj)):
            return
        async = getUtility(IAsyncService)
        tpath = '/'.join(obj.getPhysicalPath())
        job = async.queueJob(retrieve_async, obj, tpath, online=True)
        callback = job.addCallbacks(failure=job_failure_callback)
        callback  # for pep
Пример #23
0
    def get_references(self):
        """ AT references
        """
        try:
            from Products.Archetypes.interfaces import IReferenceable
            if not IReferenceable.providedBy(self.context):
                return
        except:
            return

        self['_atrefs'] = {}
        self['_atbrefs'] = {}
        relationships = self.context.getRelationships()
        for rel in relationships:
            self['_atrefs'][rel] = []
            refs = self.context.getRefs(relationship=rel)
            for ref in refs:
                if ref is not None:
                    self['_atrefs'][rel].append('/'.join(ref.getPhysicalPath()))
        brelationships = self.context.getBRelationships()
        for brel in brelationships:
            self['_atbrefs'][brel] = []
            brefs = self.context.getBRefs(relationship=brel)
            for bref in brefs:
                if bref is not None:
                    self['_atbrefs'][brel].append('/'.join(bref.getPhysicalPath()))
Пример #24
0
 def beforeChange_at_uuid(self):
     """Load AT universal uid."""
     self._checkLoadAttr('UID')
     if IReferenceable.providedBy(self.old):
         self.UID = self.old.UID()
         self.old._uncatalogUID(self.parent)
     else:
         self.UID = None
Пример #25
0
    def test_rename_updates_ref_catalog(self):
        doc1 = self.portal['doc1']
        doc2 = self.portal['doc2']
        ref_catalog = self.portal.reference_catalog
        doc1.text = RichTextValue('<a href="doc2">doc2</a>')
        modified(doc1)
        self.assertEquals(1, len(ref_catalog()))

        self.assertEquals([doc2], IReferenceable(doc1).getReferences())
        ref_brain = ref_catalog()[0]
        self.assertTrue(ref_brain.getPath().startswith('doc1'))
        self.portal.manage_renameObject(id='doc1', new_id='new_name')
        modified(doc1)
        self.assertEquals(1, len(ref_catalog()))
        ref_brain = ref_catalog()[0]
        self.assertTrue(ref_brain.getPath().startswith('new_name'))
        self.assertEquals([doc2], IReferenceable(doc1).getReferences())
Пример #26
0
 def migrate_at_uuid(self):
     """Migrate AT universal uid
     """
     if not IReferenceable.providedBy(self.old):
         return  # old object doesn't support AT uuids
     uid = self.old.UID()
     self.old._uncatalogUID(self.parent)
     self.new._setUID(uid)
Пример #27
0
 def beforeChange_at_uuid(self):
     """Load AT universal uid."""
     self._checkLoadAttr('UID')
     if IReferenceable.providedBy(self.old):
         self.UID = self.old.UID()
         self.old._uncatalogUID(self.parent)
     else:
         self.UID = None
Пример #28
0
    def test_unicode_links(self):
        doc1 = self.portal.doc1

        # This tests checks that isLinked can now be used safely as it
        # eventually plays well with transaction machinery.
        # Add bad link, should not raise exception and there should not
        # be any references added.
        self._set_text(doc1, unicode('<a href="ö?foo=bar&baz=bam">bug</a>', 'utf-8'))
        self.assertEqual(IReferenceable(doc1).getReferences(), [])
Пример #29
0
 def getuid(self):
     if HAS_PLONE_UUID:
         uid = IUUID(self.context, None)
         if uid is not None:
             return uid
     if HAS_AT:
         if IReferenceable.providedBy(self.context):
             return self.context.UID()
     return None
 def getSourceId(self, name, filename, instance, fresh=False):
     sid = ''
     if IReferenceable.providedBy(instance):
         sid = sid + instance.UID()
     sid = "%s_%s" % (sid, self.make_prefix())
     sid = "%s_%s" % (sid, name)
     fname = self.getNormalizedName(filename)
     if fname:
         sid = '%s_%s' % (sid, fname)
     return sid
Пример #31
0
 def prepareIterateObjectTabs(self, *args, **kwargs):
     tabs = self.prepareObjectTabs(*args, **kwargs)
     
     if IReferenceable.providedBy(self.context):
         iterate_control = plone.app.iterate.browser.control.Control(self.context, self.request)
         if tabs and iterate_control.checkout_allowed():
             for tab in [e for e in tabs if e['id'] == 'edit']:
                 tab['url'] = self.context.absolute_url() + '/@@content-checkout'
      
     return tabs
Пример #32
0
 def test_upgrade(self):
     doc3 = self.portal['doc3']
     doc1 = self.portal['doc1']
     self.assertTrue(IReferenceable.providedBy(doc3))
     doc3.setText('<a href="doc1">doc1</a>', mimetype='text/html')
     doc3.addReference(doc1, relationship=referencedRelationship)
     self.assertFalse(hasIncomingLinks(doc1))
     self.assertFalse(hasIncomingLinks(doc3))
     migrate_linkintegrity_relations(self.portal)
     self.assertTrue(hasIncomingLinks(doc1))
     self.assertFalse(hasIncomingLinks(doc3))
Пример #33
0
 def test_upgrade(self):
     doc3 = self.portal['doc3']
     doc1 = self.portal['doc1']
     self.assertTrue(IReferenceable.providedBy(doc3))
     doc3.setText('<a href="doc1">doc1</a>', mimetype='text/html')
     doc3.addReference(doc1, relationship=referencedRelationship)
     self.assertFalse(hasIncomingLinks(doc1))
     self.assertFalse(hasIncomingLinks(doc3))
     migrate_linkintegrity_relations(self.portal)
     self.assertTrue(hasIncomingLinks(doc1))
     self.assertFalse(hasIncomingLinks(doc3))
Пример #34
0
 def migrate_at_uuid(self):
     """Migrate AT universal uid
     """
     if not IReferenceable.providedBy(self.old):
         return  # old object doesn't support AT uuids
     uid = self.old.UID()
     self.old._uncatalogUID(self.parent)
     if queryAdapter(self.new, IMutableUUID):
         IMutableUUID(self.new).set(str(uid))
     else:
         self.new._setUID(uid)
Пример #35
0
    def test_update(self):
        doc1 = self.portal.doc1
        doc2 = self.portal.doc2
        doc4 = self.portal.folder1.doc4

        # This tests updating link integrity information for all site content,
        # i.e. after migrating from a previous version.
        self._set_text(doc1, '<a href="doc2">a document</a>')
        self._set_text(doc2, '<a href="folder1/doc4">a document</a>')
        IReferenceable(doc1).deleteReferences(relationship='isReferencing')
        IReferenceable(doc2).deleteReferences(relationship='isReferencing')

        # Just to make sure, we check that there are no references from or to
        # these documents at this point:
        self.assertEqual(IReferenceable(doc1).getReferences(), [])
        self.assertEqual(IReferenceable(doc2).getReferences(), [])

        # An update of link integrity information for all content is triggered
        # by browsing a specific url:
        transaction.commit()
        self.browser.open('{0:s}/updateLinkIntegrityInformation'.format(
            self.portal.absolute_url()))
        self.browser.getControl('Update').click()
        self.assertIn('Link integrity information updated for',
                      self.browser.contents)

        # Now the linking documents should hold the correct link integrity
        # references:
        self.assertEqual(IReferenceable(doc1).getReferences(), [
            doc2,
        ])
        self.assertEqual(IReferenceable(doc2).getReferences(), [
            doc4,
        ])
Пример #36
0
    def test_renaming_referenced_item(self):
        doc1 = self.portal.doc1
        doc2 = self.portal.doc2

        # This tests makes sure items that are linked to can still be
        # renamed (see the related bug report in #6608).  First we need
        # to create the necessary links:
        self._set_text(doc1, '<a href="doc2">doc2</a>')
        self.assertEqual(IReferenceable(doc2).getBackReferences(), [doc1])

        # Make changes visible to testbrowseropen
        transaction.commit()

        # Then we use a browser to rename the referenced image:
        self.browser.handleErrors = True
        self.browser.open('{0:s}/object_rename?_authenticator={1:s}'.format(
            doc1.absolute_url(), self._get_token(doc1)))

        self.browser.getControl(name='form.widgets.new_id').value = 'nuname'
        self.browser.getControl(name='form.buttons.Rename').click()
        self.assertIn("Renamed 'doc1' to 'nuname'.", self.browser.contents)
        transaction.commit()

        self.assertNotIn('doc1', self.portal.objectIds())
        self.assertIn('nuname', self.portal.objectIds())
        self.assertEqual(IReferenceable(doc2).getBackReferences(), [doc1])

        # We simply use a browser to try to delete a content item.
        self.browser.open(doc2.absolute_url())
        self.browser.getLink('Delete').click()
        self.assertIn('Do you really want to delete this item?',
                      self.browser.contents)
        self.browser.getControl(name='form.buttons.Delete').click()
        self.assertIn('nuname', self.portal.objectIds())

        # Link breakabe page should be shown
        self.assertIn('Potential link breakage', self.browser.contents)
        self.assertIn('<a href="http://nohost/plone/nuname">Test Page 1</a>',
                      self.browser.contents)
Пример #37
0
    def test_broken_references(self):
        # create a temporary document to test with
        doc1a = testing.create(self.portal, 'Document', id='doc1a')
        doc1 = self.portal.doc1

        self.assertEqual(len(IReferenceable(doc1).getReferences()), 0)
        self._set_text(doc1, '<a href="doc1a">Doc 1a</a>')
        self.assertEqual(len(IReferenceable(doc1).getReferences()), 1)
        self.assertEqual(IReferenceable(doc1).getReferences()[0].id,
                         self.portal.doc1a.id)

        # Now delete the target item, suppress events and test again,
        # the reference should be broken now.
        self.portal._delObject(doc1a.id, suppress_events=True)
        self.assertEqual(IReferenceable(doc1).getReferences(), [None])

        # If we now try to update the linking document again in order to
        # remove the link, things used to break raising a
        # ``ReferenceException``.  This should be handled more
        # gracefully now:
        self._set_text(doc1, 'foo!')
        self.assertEqual(IReferenceable(doc1).getReferences(), [])
Пример #38
0
 def migrate_at_uuid(self):
     """Migrate AT universal uid
     """
     if not IReferenceable.providedBy(self.old):
         return  # old object doesn't support AT uuids
     uid = self.old.UID()
     self.old._uncatalogUID(self.parent)
     if UUID_ATTR:  # Prevent object deletion triggering UID related magic
         setattr(self.old, UUID_ATTR, None)
     if queryAdapter(self.new, IMutableUUID):
         IMutableUUID(self.new).set(str(uid))
     else:
         self.new._setUID(uid)
Пример #39
0
 def migrate_at_uuid(self):
     """Migrate AT universal uid
     """
     if not IReferenceable.providedBy(self.old):
         return  # old object doesn't support AT uuids
     uid = self.old.UID()
     self.old._uncatalogUID(self.parent)
     if UUID_ATTR:  # Prevent object deletion triggering UID related magic
         setattr(self.old, UUID_ATTR, None)
     if queryAdapter(self.new, IMutableUUID):
         IMutableUUID(self.new).set(str(uid))
     else:
         self.new._setUID(uid)
Пример #40
0
    def __call__(self, skipRedirect=False, **args):
        context = self.context
        request = context.REQUEST
        if IReferenceable.providedBy(context):
            plone_utils = getToolByName(context, 'plone_utils')
            uid = request.get('uid', '')
            remoteUrl = request.get('remoteUrl', '')
            if not remoteUrl:
                message = u'No URL was given, nothing has been added.'
            else:
                util = getUtility(ISearchUrlSettings)
                urlTuples = util.urls
                existing = list()
                existing_idx = list()
                pc = context.portal_catalog
                for item in urlTuples:
                    if item.url == remoteUrl:
                        res = pc(UID=item.provider)
                        title = len(res) and res[0].Title or 'None'
                        url = len(res) and res[0].getURL() or ''
                        existing.append("existing:list=%s|%s" % (title, url))
                        existing_idx.append(urlTuples.index(item))
                if len(existing):
                    if not request.get('override', False):
                        message = u"The URL is already registered"
                        path = context.absolute_url() + "/%s?%s" % (
                            request.get('template_id', ''),
                            '&'.join(existing) )
                        plone_utils.addPortalMessage(message)
                        skipRedirect = True
                        self.request.RESPONSE.redirect(path)
                        return
                    else:
                        existing_idx.reverse()
                        for idx in existing_idx:
                            del urlTuples[idx]

                urlTuples.append(SearchUrlTuple(remoteUrl, uid))
                util.urls = urlTuples

                message = (u'"%s" has been added to search urls' %
                           unicode(context.title_or_id(), 'utf-8'))
        else:
            message = (u'"%s" could not be added to the search, because ist'
                       'is not referenceable' %
                       unicode(context.title_or_id(), 'utf-8'))

        if not skipRedirect:
            path = context.absolute_url()
            plone_utils.addPortalMessage(message)
            self.request.RESPONSE.redirect(path)
    def test_remove_cleans_ref_catalog(self):
        doc1 = self.portal['doc1']
        doc2 = self.portal['doc2']

        doc1_refs = IReferenceable(doc1)
        doc2_refs = IReferenceable(doc2)
        doc1_refs.addReference(doc2_refs, relationship='fooRelationship')

        ref_catalog = self.portal.reference_catalog
        self.assertEquals(1, len(ref_catalog()))
        self.assertEquals([doc1], doc2_refs.getBackReferences())

        self.portal.manage_delObjects(['doc1'])
        self.assertEquals(0, len(ref_catalog()))
        self.assertEquals([], doc2_refs.getBackReferences())
Пример #42
0
def apply_referenceable_behavior(context):
    # See plone.app.referenceablebehavior.uidcatalog.
    uid_catalog = getToolByName(context, 'uid_catalog')
    portal_catalog = getToolByName(context, 'portal_catalog')
    brains = portal_catalog(
        meta_type=['Dexterity Item', 'Dexterity Container'])
    for brain in brains:
        obj = brain.getObject()
        if IReferenceable.providedBy(obj):
            path = '/'.join(obj.getPhysicalPath())
            logger.info(
                """Applying referenceable behavior for
                        object at path %s""", path)
            uid_catalog.catalog_object(obj, path)
    def test_rename_updates_ref_catalog(self):
        doc1 = self.portal['doc1']
        doc2 = self.portal['doc2']

        doc1_refs = IReferenceable(doc1)
        doc2_refs = IReferenceable(doc2)
        doc1_refs.addReference(doc2_refs, relationship='fooRelationship')

        ref_catalog = self.portal.reference_catalog
        self.assertEquals(1, len(ref_catalog()))
        self.assertEquals([doc2], doc1_refs.getReferences())
        ref_brain = ref_catalog()[0]
        self.assertTrue(ref_brain.getPath().startswith('doc1'))

        self.portal.manage_renameObject(id='doc1', new_id='new_name')
        doc1 = self.portal['new_name']
        doc1_refs = IReferenceable(doc1)

        self.assertEquals(1, len(ref_catalog()))
        ref_brain = ref_catalog()[0]
        self.assertTrue(ref_brain.getPath().startswith('new_name'))
        self.assertEquals([doc2], doc1_refs.getReferences())
Пример #44
0
    def test_file_reference_linkintegrity_page_is_shown(self):
        doc1 = self.portal.doc1
        file2 = testing.create(self.portal,
                               'File',
                               id='file2',
                               file=testing.GIF)

        self._set_text(doc1, '<a href="file2">A File</a>')
        self.assertEqual(IReferenceable(doc1).getReferences(), [file2])
        self.assertIn('file2', self.portal.objectIds())

        token = self._get_token(file2)
        self.request['_authenticator'] = token

        # Make changes visible to test browser
        transaction.commit()

        self.browser.handleErrors = True
        self.browser.addHeader(
            'Authorization',
            'Basic {0:s}:{1:s}'.format(TEST_USER_NAME, TEST_USER_PASSWORD))

        delete_url = '{0:s}/object_delete?_authenticator={1:s}'.format(
            file2.absolute_url(), token)

        # Try to remove but cancel
        self.browser.open(delete_url)

        # Validate text
        self.assertIn('Potential link breakage', self.browser.contents)
        self.assertIn('removeConfirmationAction', self.browser.contents)
        self.assertIn('<a href="http://nohost/plone/doc1">Test Page 1</a>',
                      self.browser.contents)
        self.assertIn('Would you like to delete it anyway?',
                      self.browser.contents)

        # Click cancel button, item should stay in place
        self.browser.getControl(name='cancel').click()
        self.assertEqual(self.browser.url, self.portal.absolute_url())
        self.assertIn('Removal cancelled.', self.browser.contents)
        self.assertIn('file2', self.portal.objectIds())

        # Try to remove and confirm
        self.browser.open(delete_url)
        self.browser.getControl(name='delete').click()
        self.assertNotIn('file2', self.portal.objectIds())
Пример #45
0
    def links(self):
        if not IReferenceable.providedBy(self.context):
            return []

        value = []

        tasks = self.context.getBRefs('task_issues')
        tasks = sorted(
            tasks,
            lambda a, b: cmp(a.ModificationDate(), b.ModificationDate()))
        for task in tasks:
            value.append(
                dict(iterationid=task.getPhysicalPath()[-3],
                     title=abbreviate(task.Title() or task.getId(), width=25),
                     url=task.absolute_url(),
                     state=self.workflow.getInfoFor(task, 'review_state')))
        return value
Пример #46
0
    def links(self):
        if not IReferenceable.providedBy(self.context):
            return []

        value = []

        tasks = self.context.getBRefs('task_issues')
        tasks = sorted(tasks,
                       lambda a, b: cmp(a.ModificationDate(),
                                        b.ModificationDate()))
        for task in tasks:
            value.append(
                dict(iterationid=task.getPhysicalPath()[-3],
                     title=abbreviate(task.Title() or task.getId(), width=25),
                     url=task.absolute_url(),
                     state=self.workflow.getInfoFor(task, 'review_state')))
        return value
Пример #47
0
def getObjectsFromLinks(base, links):
    """ determine actual objects refered to by given links """
    objects = set()
    url = base.absolute_url()
    scheme, host, path, query, frag = urlsplit(url)
    for link in links:
        try:
            s, h, path, q, f = urlsplit(link)
        except ValueError:
            continue
        if (not s and not h) or (s == scheme and h == host):    # relative or local url
            obj, extra = findObject(base, path)
            if obj:
                if IOFSImage.providedBy(obj):
                    obj = aq_parent(obj)    # use atimage object for scaled images
                if not IReferenceable.providedBy(obj):
                    try:
                        obj = IReferenceable(obj)
                    except:
                        continue
                objects.add(obj)
    return objects
Пример #48
0
    def manageLink(self, obj, normalled):
        # need IObject iface for catalog brains
        if hasattr(obj, 'getObject'):
            # brain, other sort of pseudo object
            obj = obj.getObject()

        if not IReferenceable.providedBy(obj):
            # backlink not possible
            return

        mark(obj, IWickedTarget)
        self.refcat.addReference(obj,
                                 self.context,
                                 relationship=self.relation,
                                 referenceClass=self.refKlass)
        objuid = IUID(obj)
        path = '/'.join(obj.getPhysicalPath())
        data = dict(path=path,
                    icon=obj.getIcon(),
                    uid=objuid)

        self.cm.set((intern(str(normalled)), objuid), [data])
Пример #49
0
    def checkout_allowed(self):
        """Check if a checkout is allowed.
        """
        context = aq_inner(self.context)
        
        if not interfaces.IIterateAware.providedBy(context):
            return False
        
        if not IReferenceable.providedBy(context):
            return False

        archiver = interfaces.IObjectArchiver(context)
        if not archiver.isVersionable():
            return False

        # check if there is an existing checkout
        if len(context.getBRefs(WorkingCopyRelation.relationship)) > 0:
            return False
        
        # check if its is a checkout
        if len(context.getRefs(WorkingCopyRelation.relationship)) > 0:
            return False
        
        return True
Пример #50
0
def LCRetrieveByDate(self, skiplist=[]):
    """Retrieves the links from all objects in the site by Date."""
    sincedate = DateTime()-6*30
    since = self.REQUEST.get('since')
    if since is not None:
        since = DateTime(since)
    sincedate = since or sincedate
    offline = self.REQUEST.get('offline', '')

    pwt = self.portal_workflow
    lc = self.portal_linkchecker
    async = getUtility(IAsyncService)
    sm = getSecurityManager()
    try:
        server = lc.database._getWebServiceConnection()
    except:
        server = None
    if server is None and offline!='1':
        raise RuntimeError, "The site could not be crawled because no " \
                            "connection to the lms could be established."


#    # Not actually necessary on every crawl, but it doesn't seem to work
#    # in the installer, so this seems the next logical place to do it.
#    self.portal_catalog.reindexIndex('portal_linkchecker_uid', self.REQUEST)
    if 1:
        # gather all objects that are of a type we can check for links
        objects = self.portal_catalog(Language='all', modified={'query':sincedate,'range':'min'})
        os_ = len(objects)
        zLOG.LOG('CMFLinkChecker', zLOG.INFO, "%d objects will be crawled" % os_)
        i = 0
        for res in objects:
            i += 1
            zLOG.LOG("CMFLinkChecker", zLOG.BLATHER,
                     "Site Crawl Status",
                     "%s of %s (%s)" % (i, os_, res.getPath()))
            ob = res.getObject()
            if ob is None:
                # Maybe the catalog isn't up to date
                continue
            outdated = IAnnotatable.providedBy(ob) and \
                IAnnotations(ob).get(ANNOTATION_KEY, False) or False
            if outdated:
                zLOG.LOG("CMFLinkChecker", zLOG.INFO, "unregistering %s, object is outdated" % res.getPath())
                links = lc.database.getLinksForObject(ob)
                link_ids = [x.getId() for x in links]
                job = async.queueJob(unregister_async, lc, link_ids)
                callback = job.addCallbacks(failure=job_failure_callback)
                continue
            try:
                state = pwt.getInfoFor(ob, 'review_state')
            except:
                state = "undefined"
            if state not in ALLOWED_STATES:
                zLOG.LOG("CMFLinkChecker", zLOG.BLATHER, "unregistering, object is not public: %s" % state)
                links = lc.database.getLinksForObject(ob)
                link_ids = [x.getId() for x in links]
                job = async.queueJob(unregister_async, lc, link_ids)
                callback = job.addCallbacks(failure=job_failure_callback)
                continue
            if not sm.checkPermission(ModifyPortalContent, ob):
                continue
            if (not IReferenceable.providedBy(ob)):
                continue
            job = async.queueJob(retrieve_async, ob, res.getPath(), online=True)
            callback = job.addCallbacks(failure=job_failure_callback)
            if not i % 500 :
                transaction.savepoint()
                zLOG.LOG('CMFLinkChecker', zLOG.INFO,
                    "Crawling site - commited after %d objects" %(i))
    return "finished"
Пример #51
0
 def getWorkingCopy(self):
     if IReferenceable.providedBy(self.context):
         refs = self.context.getBRefs(WorkingCopyRelation.relationship)
         if refs:
             return refs[0]
Пример #52
0
 def get_original(self, context):
     if IReferenceable.providedBy(context):
         refs = context.getRefs(WorkingCopyRelation.relationship)
         if refs:
             return refs[0]
Пример #53
0
def retrieve(self):
  ST = []
  pc = self.portal_catalog
  link_checker = self.portal_linkchecker
  async = getUtility(IAsyncService)
  sm = getSecurityManager()
  # INitialize the helperattribute to store paths to retrieve
  objpaths = getattr(link_checker, 'objpaths', None)
  cleanup = self.REQUEST.get('cleanup', False)

  if objpaths is None or cleanup=='1':
    link_checker.objpaths = []
    objpaths = []

  # Check wheter we start fresh or need to resume
  resume = self.REQUEST.get('resume')
  debug = self.REQUEST.get('debug')
  LOG("LCRetrieveByPath", INFO, "Resuming retrieval with %s paths" % len(objpaths))

  if len(objpaths)==0 and not resume:
    path = self.REQUEST.get('path', '/'.join(self.getPhysicalPath()))
    alllangs = self.portal_languages.getSupportedLanguages()
    langs = self.REQUEST.get('langs', alllangs)
    print "path: %s" %path
    if "%s" in path:
      paths = [path%lang for lang in langs]
    else:
      paths = [path]

    LOG("LCRetrieveByPath", INFO, "Starting retrieval")

    for path in paths:
      LOG("LCRetrieveByPath", INFO, "> Path %s"%path)
      results = pc(Language='all',  path=path)
      objpaths = [x.getPath() for x in results]
      link_checker.objpaths += objpaths
      LOG("LCRetrieveByPath", INFO, "> %s results found"%len(results))

  # DONE Retrieving objpaths, start checkretrieval

  cnt = 0
  objpaths = [x for x in link_checker.objpaths]
  total = len(objpaths)
  for path in objpaths:
      if debug:
          print path
      try:
          ob = self.unrestrictedTraverse(path)
      except:
          continue
      if not ob:
          continue
      if not sm.checkPermission(ModifyPortalContent, ob):
          continue
      if (not IReferenceable.providedBy(ob)):
          continue
      outdated = IAnnotatable.providedBy(ob) and \
          IAnnotations(ob).get(ANNOTATION_KEY, False) or False
      if outdated:
          LOG("CMFLinkChecker", INFO, "unregistering %s, object is outdated" % path)
          links = link_checker.database.getLinksForObject(ob)
          link_ids = [x.getId() for x in links]
          job = async.queueJob(unregister_async, link_checker, link_ids)
          job.addCallbacks(failure=job_failure_callback)
          continue
      if not is_publically_visible(ob):
          LOG('CMFLinkChecker', INFO, "Skipping %s, obj is not public" % path)
          continue
      job = async.queueJob(retrieve_async, ob, path, online=True)
      job.addCallbacks(failure=job_failure_callback)
      LOG("LCRetrieveByPath", INFO, "> Retrieved %s"%path)
      ST.append("retrieved %s" % path)
      link_checker.objpaths.remove(path)
      link_checker._p_changed = 1
      cnt += 1
      if cnt%10==0:
          transaction.commit()
          LOG("LCRetrieveByPath", INFO, "Committing %s of %s" %(cnt, total))

  LOG("LCRetrieveByPath", INFO, "Fertig")
  return "\n".join(ST)
def getRatingVariance(obj, portal, **kw):
    if not IReferenceable.providedBy(obj):
        return None
    rt = getToolByName(obj, 'portal_ratings')    
    return rt.getRatingSumSquared(obj.UID())
def getHitCount(obj, portal, **kw):
    if not IReferenceable.providedBy(obj):
        return None
    rt = getToolByName(obj, 'portal_ratings')    
    return rt.getHitCount(obj.UID())