[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/container/browser/ fix collector issue 412: IObjectCopier.copyable() and IObjectMover.moveable()

Fred L. Drake, Jr. fdrake at gmail.com
Sat Jun 4 00:16:13 EDT 2005


Log message for revision 30639:
  fix collector issue 412: IObjectCopier.copyable() and IObjectMover.moveable()
  could not veto copying or moving an object when it was selected because they
  were not consulted
  

Changed:
  U   Zope3/trunk/src/zope/app/container/browser/contents.py
  U   Zope3/trunk/src/zope/app/container/browser/ftests/test_contents.py

-=-
Modified: Zope3/trunk/src/zope/app/container/browser/contents.py
===================================================================
--- Zope3/trunk/src/zope/app/container/browser/contents.py	2005-06-03 23:24:04 UTC (rev 30638)
+++ Zope3/trunk/src/zope/app/container/browser/contents.py	2005-06-04 04:16:10 UTC (rev 30639)
@@ -267,14 +267,36 @@
 
         container_path = zapi.getPath(self.context)
 
+        # For each item, check that it can be copied; if so, save the
+        # path of the object for later copying when a destination has
+        # been selected; if not copyable, provide an error message
+        # explaining that the object can't be copied.
+        items = []
+        for id in ids:
+            ob = self.context[id]
+            copier = IObjectCopier(ob)
+            if not copier.copyable():
+                m = {"name": id}
+                title = getDCTitle(ob)
+                if title:
+                    self.error = _(
+                        "titled-object-cannot-be-copied",
+                        "Object '${name}' (${title}) cannot be copied")
+                    m["title"] = title
+                else:
+                    self.error = _(
+                        "untitled-object-cannot-be-copied",
+                        "Object '${name}' cannot be copied")
+                self.error.mapping.update(m)
+                return
+            items.append(zapi.joinPath(container_path, id))
+
+        # store the requested operation in the principal annotations:
         user = self.request.principal
         annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
         annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         clipboard.clearContents()
-        items = []
-        for id in ids:
-            items.append(zapi.joinPath(container_path, id))
         clipboard.addItems('copy', items)
 
     def cutObjects(self):
@@ -287,14 +309,36 @@
 
         container_path = zapi.getPath(self.context)
 
+        # For each item, check that it can be moved; if so, save the
+        # path of the object for later moving when a destination has
+        # been selected; if not movable, provide an error message
+        # explaining that the object can't be moved.
+        items = []
+        for id in ids:
+            ob = self.context[id]
+            mover = IObjectMover(ob)
+            if not mover.moveable():
+                m = {"name": id}
+                title = getDCTitle(ob)
+                if title:
+                    self.error = _(
+                        "titled-object-cannot-be-moved",
+                        "Object '${name}' (${title}) cannot be moved")
+                    m["title"] = title
+                else:
+                    self.error = _(
+                        "untitled-object-cannot-be-moved",
+                        "Object '${name}' cannot be moved")
+                self.error.mapping.update(m)
+                return
+            items.append(zapi.joinPath(container_path, id))
+
+        # store the requested operation in the principal annotations:
         user = self.request.principal
         annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
         annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         clipboard.clearContents()
-        items = []
-        for id in ids:
-            items.append(zapi.joinPath(container_path, id))
         clipboard.addItems('cut', items)
 
 
@@ -402,3 +446,11 @@
 
     def index(self):
         return self._index()
+
+
+def getDCTitle(ob):
+    dc = IDCDescriptiveProperties(ob, None)
+    if dc is None:
+        return None
+    else:
+        return dc.title

Modified: Zope3/trunk/src/zope/app/container/browser/ftests/test_contents.py
===================================================================
--- Zope3/trunk/src/zope/app/container/browser/ftests/test_contents.py	2005-06-03 23:24:04 UTC (rev 30638)
+++ Zope3/trunk/src/zope/app/container/browser/ftests/test_contents.py	2005-06-04 04:16:10 UTC (rev 30639)
@@ -20,18 +20,42 @@
 
 from persistent import Persistent
 import transaction
-from zope.interface import implements
+from zope.interface import implements, Interface
 
+from zope.app import copypastemove
 from zope.app.annotation.interfaces import IAttributeAnnotatable
 from zope.app.container.interfaces import IReadContainer, IContained
 from zope.app.dublincore.interfaces import IZopeDublinCore
+from zope.app.testing import ztapi
 from zope.app.testing.functional import BrowserTestCase
 from zope.app.testing.functional import FunctionalDocFileSuite
 
 
+class IImmovable(Interface):
+    """Marker interface for immovable objects."""
+
+class IUncopyable(Interface):
+    """Marker interface for uncopyable objects."""
+
 class File(Persistent):
     implements(IAttributeAnnotatable)
 
+class ImmovableFile(File):
+    implements(IImmovable)
+
+class UncopyableFile(File):
+    implements(IUncopyable)
+
+class ObjectNonCopier(copypastemove.ObjectCopier):
+
+    def copyable(self):
+        return False
+
+class ObjectNonMover(copypastemove.ObjectMover):
+
+    def moveable(self):
+        return False
+
 class ReadOnlyContainer(Persistent):
     implements(IReadContainer, IContained)
     __parent__ = __name__ = None
@@ -282,7 +306,37 @@
         response = self.publish('/foo/@@contents.html', basic='mgr:mgrpw')
         self.assertEqual(response.getStatus(), 200)
 
+    def test_uncopyable_object(self):
+        ztapi.provideAdapter(IUncopyable,
+                             copypastemove.interfaces.IObjectCopier,
+                             ObjectNonCopier)
+        root = self.getRootFolder()
+        root['uncopyable'] = UncopyableFile()
+        transaction.commit()
+        response = self.publish('/@@contents.html',
+                                basic='mgr:mgrpw',
+                                form={'ids': [u'uncopyable'],
+                                      'container_copy_button': u'Copy'})
+        self.assertEqual(response.getStatus(), 200)
+        body = response.getBody()
+        self.assert_("cannot be copied" in body)
 
+    def test_unmoveable_object(self):
+        ztapi.provideAdapter(IImmovable,
+                             copypastemove.interfaces.IObjectMover,
+                             ObjectNonMover)
+        root = self.getRootFolder()
+        root['immovable'] = ImmovableFile()
+        transaction.commit()
+        response = self.publish('/@@contents.html',
+                                basic='mgr:mgrpw',
+                                form={'ids': [u'immovable'],
+                                      'container_cut_button': u'Cut'})
+        self.assertEqual(response.getStatus(), 200)
+        body = response.getBody()
+        self.assert_("cannot be moved" in body)
+
+
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(Test))



More information about the Zope3-Checkins mailing list