[Checkins] SVN: Products.CMFDefault/trunk/Products/CMFDefault/ - added FallbackAddView

Yvo Schubbe y.2008 at wcm-solutions.de
Wed Sep 24 07:02:33 EDT 2008


Log message for revision 91417:
  - added FallbackAddView
  - aligned ContentAddFormBase and FileAddView to the ++add++ namespace

Changed:
  U   Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt
  U   Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
  U   Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py
  U   Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt
  U   Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py
  U   Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py

-=-
Modified: Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt	2008-09-24 10:41:45 UTC (rev 91416)
+++ Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt	2008-09-24 11:02:32 UTC (rev 91417)
@@ -4,6 +4,9 @@
 2.2.0 (unreleased)
 ------------------
 
+- views: Added FallbackAddView.
+  This add form works with any portal type. It just asks for the ID.
+
 - formlib widgets: Added special input widget for object IDs.
 
 - main_template: Display action icons, thereby replacing the separate
@@ -39,7 +42,7 @@
 
 - Image, File:  make ZMI "edit" view work.
 
-- views: Added ContentEditFormBase and FileAddView.
+- views: Added ContentAddFormBase and FileAddView.
   This shows how form-driven content creation works. The content is created
   without using the constructor methods provided by the types tool.
 

Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml	2008-09-24 10:41:45 UTC (rev 91416)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml	2008-09-24 11:02:32 UTC (rev 91417)
@@ -20,6 +20,8 @@
       permission="cmf.ListFolderContents"
       />
 
+  <adapter factory=".folder.FallbackAddView" />
+
   <adapter factory=".metadata.MinimalMetadataSchemaAdapter"/>
 
   <browser:page
@@ -105,12 +107,9 @@
 
   <adapter factory=".file.FileSchemaAdapter"/>
 
-  <browser:page
-      for="Products.CMFCore.interfaces.IFolderish"
-      layer="..interfaces.ICMFDefaultSkin"
-      name="addFile.html"
-      class=".file.FileAddView"
-      permission="cmf.AddPortalContent"
+  <adapter
+      name="cmf.file"
+      factory=".file.FileAddView"
       />
 
   <browser:page

Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py	2008-09-24 10:41:45 UTC (rev 91416)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py	2008-09-24 11:02:32 UTC (rev 91417)
@@ -15,6 +15,8 @@
 $Id$
 """
 
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
 from zope.component import adapts
 from zope.formlib import form
 from zope.interface import implements
@@ -29,6 +31,7 @@
 from Products.CMFDefault.formlib.schema import ProxyFieldProperty
 from Products.CMFDefault.formlib.schema import SchemaAdapterBase
 from Products.CMFDefault.interfaces import IMutableFile
+from Products.CMFDefault.permissions import AddPortalContent
 from Products.CMFDefault.utils import Message as _
 
 
@@ -90,23 +93,23 @@
     """Add view for IMutableFile.
     """
 
+    security = ClassSecurityInfo()
+    security.declareObjectProtected(AddPortalContent)
+
     form_fields = (
         form.FormFields(IFileSchema).select('title', 'description') +
-        form.FormFields(FileUpload(__name__='file', title=_(u'Upload')),
-                        TextLine(__name__='portal_type', default=u'File'))
+        form.FormFields(FileUpload(__name__='file', title=_(u'Upload')))
         )
 
     def setUpWidgets(self, ignore_request=False):
         super(FileAddView,
               self).setUpWidgets(ignore_request=ignore_request)
         self.widgets['description'].height = 3
-        self.widgets['portal_type'].hide = True
         self.widgets['file'].displayWidth = 60
 
     def create(self, data):
         obj = super(FileAddView,
-                    self).create(dict(id=data['file'].filename,
-                                      portal_type=data['portal_type']))
+                    self).create(dict(id=data['file'].filename))
         adapted = IFileSchema(obj)
         adapted.title = data['title']
         adapted.language = u''
@@ -114,7 +117,9 @@
         adapted.file = data['file']
         return obj
 
+InitializeClass(FileAddView)
 
+
 class FileEditView(ContentEditFormBase):
 
     """Edit view for IMutableFile.

Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt	2008-09-24 10:41:45 UTC (rev 91416)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt	2008-09-24 11:02:32 UTC (rev 91417)
@@ -15,7 +15,7 @@
 
 Use the add form without input.
 
-    >>> browser.open('http://localhost/site/@@addFile.html')
+    >>> browser.open('http://localhost/site/++add++File')
     >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
     True
     >>> browser.getControl('[[zope][Add]]').click()
@@ -27,7 +27,7 @@
 Use the add form with valid input.
 
     >>> from StringIO import StringIO
-    >>> browser.open('http://localhost/site/@@addFile.html')
+    >>> browser.open('http://localhost/site/++add++File')
     >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
     True
     >>> browser.getControl(name='form.title').value = 'FILE TITLE'

Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py	2008-09-24 10:41:45 UTC (rev 91416)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py	2008-09-24 11:02:32 UTC (rev 91417)
@@ -15,8 +15,12 @@
 $Id$
 """
 
+from AccessControl import ClassSecurityInfo
 from DocumentTemplate import sequence
+from Globals import InitializeClass
 from Products.PythonScripts.standard import thousands_commas
+from zope.formlib import form
+from zope.schema import ASCIILine
 from ZTUtils import Batch
 from ZTUtils import LazyFilter
 from ZTUtils import make_query
@@ -24,6 +28,8 @@
 from Products.CMFCore.interfaces import IDynamicType
 from Products.CMFDefault.exceptions import CopyError
 from Products.CMFDefault.exceptions import zExceptions_Unauthorized
+from Products.CMFDefault.formlib.form import ContentAddFormBase
+from Products.CMFDefault.formlib.widgets import IDInputWidget
 from Products.CMFDefault.permissions import AddPortalContent
 from Products.CMFDefault.permissions import DeleteObjects
 from Products.CMFDefault.permissions import ListFolderContents
@@ -38,6 +44,35 @@
 from utils import ViewBase
 
 
+class FallbackAddView(ContentAddFormBase):
+
+    """Add view for IDynamicType content.
+    """
+
+    security = ClassSecurityInfo()
+    security.declareObjectProtected(AddPortalContent)
+
+    form_fields = form.FormFields(ASCIILine(__name__='id', title=_(u'ID')))
+    form_fields['id'].custom_widget = IDInputWidget
+
+    def createAndAdd(self, data):
+        if not self.ti.product:
+            return super(FallbackAddView, self).createAndAdd(data)
+
+        # for portal types with oldstyle factories
+        container = self.context
+        name = container.invokeFactory(self.ti.getId(), data['id'])
+        obj = container._getOb(name)
+
+        obj_type = translate(obj.Type(), container)
+        self.status = _(u'${obj_type} added.', mapping={'obj_type': obj_type})
+        self._finished_add = True
+        self._added_obj = obj
+        return obj
+
+InitializeClass(FallbackAddView)
+
+
 # XXX: This should be refactored using formlib. Please don't import from this
 #      module, things might be changed without further notice.
 

Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py	2008-09-24 10:41:45 UTC (rev 91416)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py	2008-09-24 11:02:32 UTC (rev 91417)
@@ -23,6 +23,7 @@
 from Products.Five.formlib.formbase import PageDisplayForm
 from Products.Five.formlib.formbase import PageForm
 from zope.app.container.interfaces import INameChooser
+from zope.component import adapts
 from zope.component import getUtility
 from zope.component.interfaces import IFactory
 from zope.datetime import parseDatetimetz
@@ -30,11 +31,17 @@
 from zope.i18n.interfaces import IUserPreferredLanguages
 from zope.i18n.locales import LoadLocaleError
 from zope.i18n.locales import locales
+from zope.interface import implementsOnly
+from zope.publisher.interfaces.browser import IBrowserView
 from ZTUtils import make_query
 
+from Products.CMFCore.interfaces import IFolderish
+from Products.CMFCore.interfaces import ITypeInformation
+from Products.CMFDefault.browser.utils import ViewBase
+from Products.CMFDefault.exceptions import AccessControl_Unauthorized
+from Products.CMFDefault.interfaces import ICMFDefaultSkin
 from Products.CMFDefault.utils import Message as _
 from Products.CMFDefault.utils import translate
-from Products.CMFDefault.browser.utils import ViewBase
 
 
 # from zope.publisher.http.HTTPRequest
@@ -105,6 +112,9 @@
 
 class ContentAddFormBase(_EditFormMixin, PageAddForm):
 
+    adapts(IFolderish, ICMFDefaultSkin, ITypeInformation)
+    implementsOnly(IBrowserView)
+
     actions = form.Actions(
         form.Action(
             name='add',
@@ -118,17 +128,23 @@
             success='handle_cancel_success',
             failure='handle_cancel_failure'))
 
-    description = u''
+    def __init__(self, context, request, ti):
+        self.context = context
+        self.request = request
+        self.ti = ti
+        # BBB: for Zope 2.10
+        if getattr(self.request, 'locale', None) is None:
+            self.request.locale = _getLocale(request)
 
     @property
     def label(self):
-        obj_type_id = self.widgets['portal_type']._getFormValue()
-        # look it up to get an i18n message object with correct i18n domain
-        ttool = self._getTool('portal_types')
-        fti = ttool.getTypeInfo(obj_type_id)
-        obj_type = translate(fti.Title(), self.context)
+        obj_type = translate(self.ti.Title(), self.context)
         return _(u'Add ${obj_type}', mapping={'obj_type': obj_type})
 
+    @property
+    def description(self):
+        return self.ti.Description()
+
     #same as in form.AddFormBase but without action decorator
     def handle_add(self, action, data):
         self.createAndAdd(data)
@@ -143,22 +159,23 @@
                                  ('object/folderContents', 'object/view'))
 
     def create(self, data):
-        id =  data.pop('id', '')
-        portal_type = data.pop('portal_type')
-        ttool = self._getTool('portal_types')
-        fti = ttool.getTypeInfo(portal_type)
-        factory = getUtility(IFactory, fti.factory)
+        id =  data.pop('id', '') or ''
+        factory = getUtility(IFactory, self.ti.factory)
         obj = factory(id=id, **data)
-        obj._setPortalTypeName(portal_type)
+        obj._setPortalTypeName(self.ti.getId())
         return obj
 
     def add(self, obj):
         container = self.context
+        portal_type = self.ti.getId()
 
+        # check allowed (sometimes redundant, but better safe than sorry)
+        if not self.ti.isConstructionAllowed(container):
+            raise AccessControl_Unauthorized('Cannot create %s' % portal_type)
+
         #check container constraints
         ttool = self._getTool('portal_types')
         container_ti = ttool.getTypeInfo(container)
-        portal_type = obj.getPortalTypeName()
         if container_ti is not None and \
                 not container_ti.allowType(portal_type):
             raise ValueError('Disallowed subobject type: %s' % portal_type)
@@ -168,7 +185,7 @@
         container._setObject(name, obj)
         obj = container._getOb(name)
 
-        obj_type = translate(obj.Type(), self.context)
+        obj_type = translate(obj.Type(), container)
         self.status = _(u'${obj_type} added.', mapping={'obj_type': obj_type})
         self._finished_add = True
         self._added_obj = obj
@@ -176,12 +193,11 @@
 
     def nextURL(self):
         obj = self._added_obj
-        fti = obj.getTypeInfo()
 
         message = translate(self.status, self.context)
         if isinstance(message, unicode):
             message = message.encode(self._getBrowserCharset())
-        return '%s/%s?%s' % (obj.absolute_url(), fti.immediate_view,
+        return '%s/%s?%s' % (obj.absolute_url(), self.ti.immediate_view,
                              make_query(portal_status_message=message))
 
 



More information about the Checkins mailing list