Manipulating content objects 
============================

**Common APIs used to manipulate Dexterity content objects**

In this section, we will describe some of the more commonly used APIs
that can be used to inspect and manipulate Dexterity content objects. In
most cases, the content object is referred to as *context*, its parent
folder is referred to as *folder*, and the type name is *example.type*.
Relevant imports are shown with each code snippet, though of course you
are more likely to place those at the top of the relevant code module.

Content object creation and folder manipulation
-----------------------------------------------

This section describes means to create objects and manipulate folders.

Creating a content object
~~~~~~~~~~~~~~~~~~~~~~~~~

The simplest way to create a content item is via its factory:

::

    from zope.component import createObject
    context = createObject('example.type')

At this point, the object is not acquisition wrapped. You can wrap it
explicitly by calling:

::

    wrapped = context.__of__(folder)

However, it’s normally better to add the item to a folder and then
re-get it from the folder.

Note that the factory is normally installed as a local utility, so the
*createObject()* call will only work once you’ve traversed over the
Plone site root.

There is a convenience method that can be used to create a Dexterity
object. It is mostly useful in tests:

::

    from plone.dexterity.utils import createContent
    context = createContent('example.type', title=u"Foo")

Any keyword arguments are used to set properties on the new instance
(via *setattr()* on the newly created object). This method relies on
being able to look up the FTI as a local utility, so again you must be
inside the site for it to work.

Adding an object to a container
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Once an object has been created, it can be added to a container. If the
container is a Dexterity container, or another container that supports a
dict API (e.g. a *Large Plone Folder* in Plone 3 or a container based on
*plone.folder*), you can do:

::

    folder['some_id'] = context

You should normally make sure that the *id* property of the object is
the same as the id used in the container.

If the object only supports the basic OFS API (as is the case with
standard Plone *Folders* in Plone 3), you can use the *\_setObject()*
method:

::

    folder._setObject('some_id') = context

Note that both of these approaches bypass any type checks, i.e. you can
add items to containers that would not normally allow this type of
content. Dexterity comes with a convenience function, useful in tests,
to simulate the checks performed when content is added through the web:

::

    from plone.dexterity.utils import addContentToContainer
    addContentToContainer(folder, context)

This will also invoke a name chooser and set the object’s id
accordingly, so things like the title-to-id behavior should work. As
before, this relies on local components, so you must have traversed into
a Plone site (*PloneTestCase* takes care of this for you).

To bypass folder constraints, you can use this function and pass
*checkConstraints=False*.

You can also both create and add an object in one call:

::

    from plone.dexterity.utils import createContentInContainer
    createContentInContainer(folder, 'example.type', title=u"Foo")

Again, you can pass *checkConstraints=False* to bypass folder
constraints, and pass object properties as keyword arguments.

Finally, you can use the *invokeFactory()* API, which is similar, but
more generic in that it can be used for any type of content, not just
Dexterity content:

::

    new_id = folder.invokeFactory('example.type', 'some_id')
    context = folder['new_id']

This always respects add constraints, including add permissions and the
current user’s roles.

Getting items from a folder
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Dexterity containers and other containers based on *plone.folder*
support a dict-like API to obtain and manipulate items in folders. For
example, to obtain an (acquisition-wrapped) object by name:

::

    context = folder['some_id']

Folders can also be iterated over, and you can all *items()*, *keys()*,
*values()* and so on, treating the folder as a dict with string keys and
content objects as values.

Dexterity containers also support the more basic OFS API. You can call
*objectIds()* to get keys, *objectValues()* to get a list of content
objects, *objectItems()* to get an *items()*-like dict,and
*hasObject(id)* to check if an object exists in a container.

Removing items from a folder
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Again, Dexterity containers act like dictionaries, and so implement
*\_\_delitem\_\_*:

::

    del folder['some_id']

The OFS API uses the *\_delObject()* function for the same purpose:

::

    folder._delObject('some_id')

Object introspection
--------------------

This section describes means of getting information about an object.

Obtaining an object’s schema interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A content object’s schema is an interface, i.e. an object of type
*zope.interface.interface.InterfaceClass*.

::

    from zope.app.content import queryContentType
    schema = queryContentType(context)

The schema can now be inspected. For example:

::

    from zope.schema import getFieldsInOrder
    fields = getFieldsInOrder(schema)

Finding an object’s behaviors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To find all behaviors supported by an object, use the *plone.behavior*
API:

::

    from plone.behavior.interfaces import IBehaviorAssignable
    assignable = IBehaviorAssignable(context)
    for behavior in assignable.enumerateBehaviors():
        behavior_schema = behavior.interface
        adapted = behavior_schema(context)
        ...

The objects returned are instances providing
*plone.behavior.interfaces.IBehavior*. To get the behavior schema, use
the *interface* property of this object. You can inspect this and use it
to adapt the context if required.

Getting the FTI
~~~~~~~~~~~~~~~

To obtain a Dexterity FTI, look it up as a local utility:

::

    from zope.component import getUtility
    from plone.dexterity.interfaces import IDexterityFTI
    fti = getUtility(IDexterityFTI, name='example.type')

The returned object provides *plone.dexterity.interfaces.IDexterityFTI*.
To get the schema interface for the type from the FTI, you can do:

::

    schema = fti.lookupSchema()

Getting the object’s parent folder
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A Dexterity item in a Dexterity container should have the
*\_\_parent\_\_* property set, pointing to its containment parent:

::

    folder = context.__parent__

Items in standard Plone folders won’t have this property set, at least
not in Plone 3.x.

The more general approach relies on acquisition:

::

    from Acquisition import aq_inner, aq_parent
    folder = aq_parent(aq_inner(context))

Workflow
--------

This section describes ways to inspect an object’s workflow state and
invoke transitions.

Obtaining the workflow state of an object
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To obtain an object’s workflow state, ask the*portal\_workflow* tool:

::

    from Products.CMFCore.utils import getToolByName
    portal_workflow = getToolByName(context, 'portal_workflow')
    review_state = portal_workflow.getInfoFor(context, 'review_state')

This assumes that the workflow state variable is called *review\_state*,
as is the case for almost all workflows.

Invoking a workflow transition
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To invoke a transition:

::

    portal_workflow.doActionFor(context, 'some_transition')

The transition must be available in the current workflow state, for the
current user. Otherwise, an error will be raised.

Cataloging and indexing
-----------------------

This section describes ways of indexing an object in the portal\_catalog
tool.

Reindexing the object
~~~~~~~~~~~~~~~~~~~~~

Objects may need to be reindexed if they are modified in code. The best
way to reindex them is actually to send an event and let Dexterity’s
standard event handlers take care of this:

::

    from zope.lifecycleevent import modified
    modified(context)

In tests, it is sometimes necessary to reindex explicitly. This can be
done with:

::

    context.reindexObject()

You can also pass specific index names to reindex, if you don’t want to
reindex everything:

::

    context.reindexObject(idxs=['Title', 'sortable_title'])

This method comes from the
*Products.CMFCore.CMFCatalogAware.CMFCatalogAware* mix-in class.

Security
--------

This section describes ways to check and modify permissions. For more
information, see the section on `permissions`_.

Checking a permission
~~~~~~~~~~~~~~~~~~~~~

To check a permission by its Zope 3 name:

::

    from zope.security import checkPermission
    checkPermission('zope2.View', context)

Note: In a test, you may get an AttributeError when calling this method.
To resolve this, call *newInteraction()* from *Products.Five.security*
in your test setup (e.g. the *afterSetUp()* method).

To use the Zope 2 permission title:

::

    from AccessControl import getSecurityManager
    getSecurityManager().checkPermission('View', context)

Sometimes, normally in tests, you want to know which roles have a
particular permission. To do this, use:

::

    roles = [r['name'] for r in context.rolesOfPermission('View') if r['selected']]

Again, note that this uses the Zope 2 permission title.

Changing permissions
~~~~~~~~~~~~~~~~~~~~

Normally, permissions should be set with workflow, but in tests it is
often useful to manipulate security directly:

::

    context.manage_permission('View', roles=['Manager', 'Owner'], acquire=True)

Again note that this uses the Zope 2 permission title.

Content object properties and methods
-------------------------------------

The following table shows the more important properties and methods
available on Dexterity content objects. In addition, any field described
in the type’s schema will be available as a property, and can be read
and set using normal attribute access.

+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Property/method       | Type          | Description                                                                                                                                                                                                                                                                                                                                                                                |
+=======================+===============+============================================================================================================================================================================================================================================================================================================================================================================================+
| \_\_name\_\_          | unicode       | The name (id) of the object in its container. This is a unicode string to be consistent with the Zope 3 *IContained* interface, although in reality it will only ever contain ASCII characters, since Zope 2 does not support non-ASCII URLs.                                                                                                                                              |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id                    | str           | The name (id) of the object in its container. This is an ASCII string encoding of the *\_\_name\_\_*.                                                                                                                                                                                                                                                                                      |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| getId()               | str           | Returns the value of the *id*property*.*                                                                                                                                                                                                                                                                                                                                                   |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| isPrincipaFolderish   | bool/int      | True (or 1) if the object is a folder. False (or 0) otherwise.                                                                                                                                                                                                                                                                                                                             |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| portal\_type          | str           | The portal\_type of this instance. Should match an FTI in the *portal\_types* tool. For Dexterity types, should match a local utility providing *IDexterityFTI*. Note that the *portal\_type* is a per-instance property set upon creation (by the factory), and should not be set on the class.                                                                                           |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| meta\_type            | str           | A Zope 2 specific way to describe a class. Rarely, if ever, used in Dexterity. Do not set it on your own classes unless you know what you’re doing.                                                                                                                                                                                                                                        |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| title\_or\_id()       | str           | Returns the value of the *title* property or, if this is not set, the *id* property.                                                                                                                                                                                                                                                                                                       |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| absolute\_url()       | str           | The full URL to the content object. Will take virtual hosting and the current domain into account.                                                                                                                                                                                                                                                                                         |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| getPhysicalPath()     | tuple         | A sequence of string path elements from the application root. Stays the same regardless of virtual hosting and domain. A common pattern is to use *‘/’.join(context.getPhysicalPath())* to get a string representing the path to the Zope application root. Note that it is *not* safe to construct a relative URL from the path, because it does not take virtual hosting into account.   |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| getIcon()             | str           | Returns a string suitable for use in the *src* attribute of an *<img />* tag to get the icon of the content object.                                                                                                                                                                                                                                                                        |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| title                 | unicode/str   | Property representing the title of the content object. Usually part of an object’s schema or provided by the *IBasic* behavior. The default is an empty string.                                                                                                                                                                                                                            |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Title()               | unicode/str   | Dublin Core accessor for the *title* property. Set the title by modifying this property. You can also use *setTitle()*.                                                                                                                                                                                                                                                                    |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| listCreators()        | tuple         | A list of user ids for object creators. The first creator is normally the owner of the content object. You can set this list using the *setCreators()* method.                                                                                                                                                                                                                             |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Creator()             | str           | The first creator returned by the *listCreators()* method. Usually the owner of the content object.                                                                                                                                                                                                                                                                                        |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Subject()             | tuple         | Dublin Core accessor for item keywords. You can set this list using the *setSubject()* method.                                                                                                                                                                                                                                                                                             |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Description()         | unicode/str   | Dublin Core accessor for the *description* property, which is usually part of an object’s schema or provided by the *IBasic* behavior. You can set the description by setting the *description* attribute, or using the *setDescription()* method.                                                                                                                                         |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| listContributors()    | tuple         | Dublin Core accessor for the list of object contributors. You can set this with *setContributors()*.                                                                                                                                                                                                                                                                                       |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Date()                | str           | Dublin Core accessor for the default date of the content item, in ISO format. Uses the effective date is set, falling back on the modification date.                                                                                                                                                                                                                                       |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| CreationDate()        | str           | Dublin Core accessor for the creation date of the content item, in ISO format.                                                                                                                                                                                                                                                                                                             |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EffectiveDate()       | str           | Dublin Core accessor for the effective publication date of the content item, in ISO format. You can set this by passing a DateTime object to *setEffectiveDate()*.                                                                                                                                                                                                                         |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ExpirationDate()      | str           | Dublin Core accessor for the content expiration date, in ISO format. You can set this by passing a DateTime object to *setExpirationDate()*.                                                                                                                                                                                                                                               |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ModificationDate()    | str           | Dublin Core accessor for the content last-modified date, in ISO format.                                                                                                                                                                                                                                                                                                                    |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Language()            | str           | Dublin Core accessor for the content language. You can set this using *setLanguage()*.                                                                                                                                                                                                                                                                                                     |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Rights()              | str           | Dublin Core accessor for content copyright information. You can set this using *setRights()*.                                                                                                                                                                                                                                                                                              |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| created()             | DateTime      | Returns the Zope 2 DateTime for the object’s creation date. If not set, returns a “floor” date of January 1st, 1970.                                                                                                                                                                                                                                                                       |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| modified()            | DateTime      | Returns the Zope 2 DateTime for the object’s modification date. If not set, returns a “floor” date of January 1st, 1970.                                                                                                                                                                                                                                                                   |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| effective()           | DateTime      | Returns the Zope 2 DateTime for the object’s effective date. If not set, returns a “floor” date of January 1st, 1970.                                                                                                                                                                                                                                                                      |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| expires()             | DateTime      | Returns the Zope 2 DateTime for the object’s expiration date. If not set, returns a “floor” date of January 1st, 1970.                                                                                                                                                                                                                                                                     |
+-----------------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

.. _permissions: ../advanced/permissions.html
