Exemple #1
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)
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)
Exemple #3
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])
Exemple #4
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])
Exemple #5
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])
    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())
Exemple #7
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
Exemple #8
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())
Exemple #9
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())
Exemple #10
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)
Exemple #11
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())
Exemple #12
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(), [])
Exemple #13
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
Exemple #14
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,
        ])
    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())
Exemple #16
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)
Exemple #17
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(), [])
Exemple #18
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())
Exemple #19
0
    def test_file_reference_throws_exception(self):
        """This tests the behaviour when removing a referenced file."""

        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

        # Throws exception which actually should abort transaction
        view = file2.restrictedTraverse('@@object_delete')
        self.assertRaises(exceptions.LinkIntegrityNotificationException, view)
Exemple #20
0
def update_link_integrity(obj, event):
    """Update link integrity information on modification/removal of
    tiles.

    :param obj: cover object that was modified
    :type obj: Dexterity-based content type
    :param event: event fired
    :type event:
    """
    refs = obj.get_referenced_objects()

    if IS_PLONE_5:
        updateReferences(obj, refs)
    else:
        # needed by plone.app.linkintegrity under Plone 4.x
        adapted = IReferenceable(obj, None)
        if adapted is None:
            return
        updateReferences(adapted, referencedRelationship, refs)
Exemple #21
0
    def test_reference_orthogonality(self):
        doc = self.portal.doc1
        img = self.portal.image1
        tag = img.restrictedTraverse('@@images').tag()

        # This tests the behavior when other references already exist.
        self.assertEqual(IReferenceable(doc).getReferences(), [])
        self.assertEqual(IReferenceable(doc).getBackReferences(), [])
        self.assertEqual(IReferenceable(img).getReferences(), [])
        self.assertEqual(IReferenceable(img).getBackReferences(), [])

        # Then establish a reference between the document and image as
        # a related item:
        self._set_related_items(doc, [img, ])
        self.assertEqual(self._get_related_items(doc), [img, ])

        # Next edit the document body and insert a link to the image,
        # which should trigger the creation of a link integrity reference:
        self._set_text(doc, tag)

        from plone.app.linkintegrity.handlers import referencedRelationship
        self.assertEqual(IReferenceable(doc).getReferences(
            relationship=referencedRelationship), [img, ])

        # And the related item reference remains in place:
        self.assertEqual(self._get_related_items(doc), [img, ])

        # Finally, edit the document body again, this time removing the
        # link to the image, which should trigger the removal of the
        # link integrity reference:
        self._set_text(doc, 'where did my link go?')
        self.assertEqual(IReferenceable(doc).getReferences(
            relationship=referencedRelationship), [])

        # And again the related item reference remains in place:
        self.assertEqual(self._get_related_items(doc), [img, ])
Exemple #22
0
 def test_relative_upwards_link_generates_matching_reference(self):
     doc1 = self.portal.doc1
     doc3 = self.portal.folder1.doc3
     self._set_text(doc3, '<a href="../doc1">go!</a>')
     self.assertEqual(IReferenceable(doc3).getReferences(), [doc1])
Exemple #23
0
def deleteReferences(context, event):
    """
    """
    IReferenceable(context).deleteReferences()