===================
Supermodel handlers
===================

This package contains handlers for two plone.supermodel namespaces: ``form``,
which can be used to set widgets, omitted fields, field modes and field
order, and ``security``, which can be used to set field read and write
permissions.

Test setup
----------

First, let's load this package's ZCML so that we can run the tests:

    >>> configuration = """\
    ... <configure xmlns="http://namespaces.zope.org/zope">
    ...
    ...     <include package="Products.Five" file="configure.zcml" />
    ...     <include package="plone.autoform" />
    ...     
    ... </configure>
    ... """
    >>> from StringIO import StringIO
    >>> from zope.configuration import xmlconfig
    >>> xmlconfig.xmlconfig(StringIO(configuration))

XML sample
----------

Next, let's define a sample model that exercises the various ``form`` and
``security`` attributes.

    >>> schema = """\
    ... <?xml version="1.0" encoding="UTF-8"?>
    ... <model xmlns="http://namespaces.plone.org/supermodel/schema"
    ...        xmlns:form="http://namespaces.plone.org/supermodel/form"
    ...        xmlns:security="http://namespaces.plone.org/supermodel/security">
    ...     <schema>
    ...         <field type="zope.schema.TextLine" name="one"
    ...                 form:omitted="true"
    ...                 form:after="two"
    ...                 security:read-permission="zope2.View"
    ...                 security:write-permission="cmf.ModifyPortalContent">
    ...             <title>One</title>
    ...         </field>
    ...         <field type="zope.schema.TextLine" name="two"
    ...                form:mode="hidden">
    ...             <title>Two</title>
    ...         </field>
    ...         <field type="zope.schema.TextLine" name="three"
    ...                 form:before="two"
    ...                 form:widget="z3c.form.browser.password.PasswordFieldWidget"
    ...                 form:validator="plone.autoform.tests.test_utils.TestValidator"
    ...                 form:omitted="z3c.form.interfaces.IForm:true z3c.form.interfaces.IEditForm:false"
    ...                 form:mode="z3c.form.interfaces.IEditForm:input">
    ...             <title>Three</title>
    ...         </field>
    ...     </schema>
    ... </model>
    ... """

Notes:

* To omit a field from all forms, use ``form:omitted="true"``.  To omit a field
  only from some forms, specify a form interface like
  ``form:omitted="z3c.form.interfaces.IForm:true"``. Multiple interface:value
  settings may be specified, separated by spaces.
* To re-order fields, use ``form:after`` or ``form:before``. The value should
  be either ``'*'``, to put the field first/last in the form, or the name of a
  another field. Use ``'.fieldname'`` to refer to field in the current schema
  (or a base schema). Use a fully prefixed name (e.g.
  ``'my.package.ISomeSchema'``) to refer to a field in another schema. Use an
  unprefixed name to refer to a field in the default schema for the form.
* To turn a field into a view mode or hidden field, use ``form:mode``.  The
  mode may be set for only some forms by specifying a form interface in the
  same manner as for ``form:omitted``.
* To set a custom widget for a field, use ``form:widget`` to give a fully
  qualified name to the field widget factory.
* To set a custom validator for a field, use ``form:validator`` to give a fully
  qualified name to the field validator factory.
* To set a read or write permission, use ``security:read-permission`` or
  ``security:write-permission``. The value should be the name of an 
  ``IPermission`` utility.

We can load this using plone.supermodel:

    >>> from plone.supermodel import loadString
    >>> model = loadString(schema)

The interface defined in the model should now have the relevant form data:

    >>> from plone.autoform.interfaces import OMITTED_KEY, WIDGETS_KEY, \
    ...     MODES_KEY, ORDER_KEY, READ_PERMISSIONS_KEY, WRITE_PERMISSIONS_KEY
    >>> model.schema.getTaggedValue(WIDGETS_KEY)
    {'three': 'z3c.form.browser.password.PasswordFieldWidget'}
    >>> model.schema.getTaggedValue(OMITTED_KEY)
    [(<InterfaceClass zope.interface.Interface>, 'one', 'true'), (<InterfaceClass z3c.form.interfaces.IForm>, 'three', 'true'), (<InterfaceClass z3c.form.interfaces.IEditForm>, 'three', 'false')]
    >>> model.schema.getTaggedValue(ORDER_KEY)
    [('one', 'after', 'two'), ('three', 'before', 'two')]
    >>> model.schema.getTaggedValue(MODES_KEY)
    [(<InterfaceClass z3c.form.interfaces.IEditForm>, 'three', 'input'), (<InterfaceClass zope.interface.Interface>, 'two', 'hidden')]
    >>> model.schema.getTaggedValue(READ_PERMISSIONS_KEY)
    {'one': 'zope2.View'}
    >>> model.schema.getTaggedValue(WRITE_PERMISSIONS_KEY)
    {'one': 'cmf.ModifyPortalContent'}

See autoform.txt for details on how this form data is used to manipulate
form layout.
