[Checkins] SVN: Products.CMFDefault/trunk/Products/CMFDefault/ - moved FallbackAddView to formlib.form
Yvo Schubbe
y.2009 at wcm-solutions.de
Wed Aug 26 15:51:01 EDT 2009
Log message for revision 103239:
- moved FallbackAddView to formlib.form
- added functional tests that show how to use ContentAddFormBase and FallbackAddView
Changed:
U Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
U Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/configure.zcml
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py
A Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.txt
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/tests.py
-=-
Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml 2009-08-26 19:39:25 UTC (rev 103238)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml 2009-08-26 19:51:00 UTC (rev 103239)
@@ -20,15 +20,6 @@
permission="cmf.ListFolderContents"
/>
- <adapter factory=".folder.FallbackAddView" />
-
- <class class=".folder.FallbackAddView">
- <require
- permission="cmf.AddPortalContent"
- interface="zope.formlib.interfaces.IPageForm"
- />
- </class>
-
<adapter factory=".metadata.MinimalMetadataSchemaAdapter"/>
<browser:page
Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py 2009-08-26 19:39:25 UTC (rev 103238)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/folder.py 2009-08-26 19:51:00 UTC (rev 103239)
@@ -17,8 +17,6 @@
from DocumentTemplate import sequence # for sort()
from Products.PythonScripts.standard import thousands_commas
-from zope.formlib.form import FormFields
-from zope.schema import ASCIILine
from ZTUtils import Batch
from ZTUtils import LazyFilter
from ZTUtils import make_query
@@ -29,8 +27,6 @@
from Products.CMFDefault.browser.utils import ViewBase
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
@@ -41,30 +37,6 @@
from Products.CMFDefault.utils import translate
-class FallbackAddView(ContentAddFormBase):
-
- """Add view for IDynamicType content.
- """
-
- form_fields = 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
-
-
# 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/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/configure.zcml 2009-08-26 19:39:25 UTC (rev 103238)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/configure.zcml 2009-08-26 19:51:00 UTC (rev 103239)
@@ -11,4 +11,13 @@
permission="zope.Public"
/>
+ <adapter factory=".form.FallbackAddView" />
+
+ <class class=".form.FallbackAddView">
+ <require
+ permission="cmf.AddPortalContent"
+ interface="zope.formlib.interfaces.IPageForm"
+ />
+ </class>
+
</configure>
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py 2009-08-26 19:39:25 UTC (rev 103238)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py 2009-08-26 19:51:00 UTC (rev 103239)
@@ -30,12 +30,14 @@
from zope.formlib import form
from zope.formlib.interfaces import IPageForm
from zope.interface import implementsOnly
+from zope.schema import ASCIILine
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.formlib.widgets import IDInputWidget
from Products.CMFDefault.interfaces import ICMFDefaultSkin
from Products.CMFDefault.utils import Message as _
from Products.CMFDefault.utils import translate
@@ -168,6 +170,30 @@
make_query(portal_status_message=message))
+class FallbackAddView(ContentAddFormBase):
+
+ """Add view for IDynamicType content.
+ """
+
+ 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
+
+
class ContentEditFormBase(_EditFormMixin, PageForm):
actions = form.Actions(
Added: Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.txt (rev 0)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.txt 2009-08-26 19:51:00 UTC (rev 103239)
@@ -0,0 +1,113 @@
+Add Forms
+---------
+
+Set up user.
+
+ >>> uf = app.site.acl_users
+ >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+ >>> from Products.Five.testbrowser import Browser
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+ >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Register the content class and factory.
+
+ >>> from Products.CMFDefault.formlib.tests import CONTENT_ZCML
+ >>> from Products.Five import zcml
+ >>> zcml.load_string(CONTENT_ZCML)
+
+Create the type info object.
+
+ >>> from Products.CMFDefault.formlib.tests import MYFOO_XML
+ >>> from Products.CMFDefault.formlib.tests import TYPES_XML
+ >>> from Products.GenericSetup.context import SetupEnviron
+ >>> from Products.GenericSetup.interfaces import IBody
+ >>> from zope.component import getMultiAdapter
+
+ >>> ttool = app.site.portal_types
+ >>> context = SetupEnviron()
+ >>> context._should_purge = False
+ >>> importer = getMultiAdapter((ttool, context), IBody)
+ >>> importer.body = TYPES_XML
+ >>> importer = getMultiAdapter((ttool.MyFoo, context), IBody)
+ >>> importer.body = MYFOO_XML
+
+If no add view is registered for 'test.foo' the fallback add view is used. It
+just has an ID field.
+
+ >>> browser.open('http://localhost/site/++add++MyFoo')
+ >>> '[[cmf_default][Add [[cmf_default][MyFoo]]]]' in browser.contents
+ True
+ >>> browser.getControl(name='form.bar')
+ Traceback (most recent call last):
+ ...
+ LookupError: name 'form.bar'
+ >>> browser.getControl(name='form.id').value = 'MY_ID'
+ >>> browser.getControl('[[zope][Add]]').click()
+ >>> '[[cmf_default][[[cmf_default][MyFoo]] added.]]' in browser.contents
+ True
+ >>> 'MY_ID' in app.site.contentIds()
+ True
+
+This is the most simple add form you can create for 'test.foo'. Add views
+always belong to specific content factories. The name of the factory and the
+name of the add view have to be the same.
+
+ >>> from zope.component import getSiteManager
+ >>> from zope.formlib import form
+ >>> from Products.CMFDefault.formlib.form import ContentAddFormBase
+ >>> from Products.CMFDefault.formlib.tests import IFoo
+
+ >>> class FooAddView(ContentAddFormBase):
+ ... form_fields = form.FormFields(IFoo)
+ >>> getSiteManager().registerAdapter(FooAddView, name='test.foo')
+
+The customized add form has the same title but no ID field. On the other hand
+it has the fields defined in IFoo.
+
+ >>> browser.open('http://localhost/site/++add++MyFoo')
+ >>> '[[cmf_default][Add [[cmf_default][MyFoo]]]]' in browser.contents
+ True
+ >>> browser.getControl(name='form.id')
+ Traceback (most recent call last):
+ ...
+ LookupError: name 'form.id'
+ >>> browser.getControl(name='form.bar').value = 'BAR'
+ >>> browser.getControl(name='form.baz').value = 'BAZ'
+ >>> browser.getControl('[[zope][Add]]').click()
+ >>> '[[cmf_default][[[cmf_default][MyFoo]] added.]]' in browser.contents
+ True
+ >>> 'Foo' in app.site.contentIds()
+ True
+
+Now we add again the ID field.
+
+ >>> from Products.CMFDefault.formlib.widgets import IDInputWidget
+ >>> from Products.CMFDefault.utils import Message as _
+ >>> from zope.schema import ASCIILine
+
+ >>> class FooAddView(ContentAddFormBase):
+ ... form_fields = (
+ ... form.FormFields(ASCIILine(__name__='id', title=_(u'ID'))) +
+ ... form.FormFields(IFoo)
+ ... )
+ ... form_fields['id'].custom_widget = IDInputWidget
+ >>> getSiteManager().registerAdapter(FooAddView, name='test.foo')
+
+The customized add form has the ID field and the fields defined in IFoo.
+
+ >>> browser.open('http://localhost/site/++add++MyFoo')
+ >>> '[[cmf_default][Add [[cmf_default][MyFoo]]]]' in browser.contents
+ True
+ >>> browser.getControl(name='form.id').value = 'MY_ID2'
+ >>> browser.getControl(name='form.bar').value = 'BAR'
+ >>> browser.getControl(name='form.baz').value = 'BAZ'
+ >>> browser.getControl('[[zope][Add]]').click()
+ >>> '[[cmf_default][[[cmf_default][MyFoo]] added.]]' in browser.contents
+ True
+ >>> 'MY_ID2' in app.site.contentIds()
+ True
+
Property changes on: Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/tests.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/tests.py 2009-08-26 19:39:25 UTC (rev 103238)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/tests.py 2009-08-26 19:51:00 UTC (rev 103239)
@@ -17,11 +17,78 @@
import unittest
import Testing
+from Testing import ZopeTestCase
from zope.testing import doctest
+from Products.CMFCore.PortalContent import PortalContent
+from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
+from Products.CMFDefault.testing import FunctionalLayer
+from zope.component.factory import Factory
+from zope.interface import implements
+from zope.interface import Interface
+from zope.schema import TextLine
+CONTENT_ZCML = """\
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five">
+
+ <five:registerClass
+ class="Products.CMFDefault.formlib.tests.Foo"
+ meta_type="Foo Type"
+ permission="cmf.AddPortalContent"
+ />
+
+ <utility
+ component="Products.CMFDefault.formlib.tests.FooFactory"
+ name="test.foo"
+ />
+
+</configure>
+"""
+
+TYPES_XML = """\
+<?xml version="1.0"?>
+<object name="portal_types">
+ <object name="MyFoo" meta_type="Factory-based Type Information"/>
+</object>
+"""
+
+MYFOO_XML = """\
+<?xml version="1.0"?>
+<object name="MyFoo">
+ <property name="content_meta_type">Foo Type</property>
+ <property name="factory">test.foo</property>
+ <property name="add_view_expr">string:${folder_url}/++add++MyFoo</property>
+ <action title="View" action_id="view" category="object" url_expr=""/>
+</object>
+"""
+
+
+class IFoo(Interface):
+
+ bar = TextLine(title=u'Bar')
+ baz = TextLine(title=u'Baz')
+
+
+class Foo(PortalContent, DefaultDublinCoreImpl):
+
+ implements(IFoo)
+
+ def __init__(self, id, bar='', baz=''):
+ DefaultDublinCoreImpl.__init__(self)
+ self.id = id
+ self.bar = bar
+ self.baz = baz
+
+FooFactory = Factory(Foo)
+
+
def test_suite():
suite = unittest.TestSuite()
+ s = ZopeTestCase.FunctionalDocFileSuite('form.txt')
+ s.layer = FunctionalLayer
+ suite.addTest(s)
suite.addTest(doctest.DocFileSuite('schema.txt',
optionflags=doctest.NORMALIZE_WHITESPACE))
suite.addTest(doctest.DocFileSuite('widgets.txt',
More information about the Checkins
mailing list