<?xml version="1.0" encoding="UTF-8" ?>
<rdf:RDF xmlns="http://usefulinc.com/ns/doap#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Project><name>z3ext.content</name>
<shortdesc>z3ext content - Alternative implementation of content types system.</shortdesc>
<description>Detailed Documentation
======================


=======================
z3ext:content directive
=======================

Alternative implementation of content types system.

   &gt;&gt;&gt; import z3ext.content
   &gt;&gt;&gt; from z3ext.content import interfaces, constraints, item, tests

   &gt;&gt;&gt; from zope.configuration import xmlconfig
   &gt;&gt;&gt; context = xmlconfig.file('meta.zcml', z3ext.content)

We can register new content type with `z3ext:content` directive.
Let's create schema and implementation for our type.

   &gt;&gt;&gt; from zope import interface, component, schema

   &gt;&gt;&gt; class IMyContent(interface.Interface):
   ...     
   ...     title = schema.TextLine(
   ...         title = u'Title')

   &gt;&gt;&gt; class MyContent(item.Item):
   ...     interface.implements(IMyContent)
   ...     
   ...     def __init__(self, title):
   ...         self.title = title

   &gt;&gt;&gt; context = xmlconfig.string("""
   ... &lt;configure xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="z3ext"&gt;
   ...   &lt;z3ext:content
   ...     name="myContent"
   ...     title="My content"
   ...     class="z3ext.content.TESTS.MyContent"
   ...     schema="z3ext.content.TESTS.IMyContent"
   ...     description="Simple content type." /&gt;
   ... &lt;/configure&gt;""", context)

We can get content type as named utility.

   &gt;&gt;&gt; ctContent = component.getUtility(interfaces.IContentType, 'myContent')

   &gt;&gt;&gt; ctContent.name, ctContent.klass, ctContent.title
   (u'myContent', &lt;class 'z3ext.content.TESTS.MyContent'&gt;, u'My content')

We can create content instance

   &gt;&gt;&gt; content = ctContent.create(u'Title')
   &gt;&gt;&gt; isinstance(content, MyContent)
   True

Content type for content object

   &gt;&gt;&gt; print interfaces.IContentType(content)
   &lt;BoundContentType:z3ext.content.contenttype.ContentType myContent 'My content'&gt;


Content Type binding
--------------------

We can use content types for various tasks like adding new content, 
check availability of content type, etc. Content type should be bound to 
some context

   &gt;&gt;&gt; interfaces.IBoundContentType.providedBy(ctContent)
   False

   &gt;&gt;&gt; print ctContent
   &lt;ContentType:z3ext.content.contenttype.ContentType myContent 'My content'&gt;

Now we need content

   &gt;&gt;&gt; from zope.app.container.sample import SampleContainer
   &gt;&gt;&gt; container = SampleContainer()

Now let's bind content type to container

   &gt;&gt;&gt; bctContent = ctContent.__bind__(container)
   
   &gt;&gt;&gt; interfaces.IBoundContentType.providedBy(bctContent)
   True

   &gt;&gt;&gt; print bctContent
   &lt;BoundContentType:z3ext.content.contenttype.ContentType myContent 'My content'&gt;


Content Type availability
-------------------------

Unbound content type is always unavailable. By default z3ext.content register only
one checker for permission checks.

   &gt;&gt;&gt; ctContent.isAvailable()
   False

   &gt;&gt;&gt; bctContent.isAvailable()
   True

We can define new avilability checks. We need new adapter to IContentTypeChecker
interface. We define checker that fail is content type name is 'failed.container'

   &gt;&gt;&gt; class NameChecker(object):
   ...    interface.implements(interfaces.IContentTypeChecker)
   ...    component.adapts(interfaces.IContentType, interface.Interface)
   ...    
   ...    def __init__(self, contenttype, context):
   ...        self.contenttype = contenttype
   ...        self.context = context
   ...
   ...    def check(self):
   ...        return not (self.contenttype.name == 'failed.container')

   &gt;&gt;&gt; component.provideAdapter(NameChecker, name='mychecker')

   &gt;&gt;&gt; bctContent.name = 'failed.container'
   &gt;&gt;&gt; bctContent.isAvailable()
   False

   &gt;&gt;&gt; bctContent.name = 'any'
   &gt;&gt;&gt; bctContent.isAvailable()
   True

   &gt;&gt;&gt; sm = component.getSiteManager()
   &gt;&gt;&gt; t = sm.unregisterAdapter(NameChecker, name='mychecker')


Adding Content
--------------

We can add content only if container content type can contain content types.
Let's register container content type

   &gt;&gt;&gt; from z3ext.content.container import ContentContainer

   &gt;&gt;&gt; class IMyContainer(interfaces.IItem):
   ...     pass

   &gt;&gt;&gt; class MyContainer(ContentContainer):
   ...     interface.implements(IMyContainer)

   &gt;&gt;&gt; context = xmlconfig.string("""
   ... &lt;configure xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="z3ext"&gt;
   ...   &lt;z3ext:content
   ...     name="myContainer"
   ...     title="My container"
   ...     class="z3ext.content.TESTS.MyContainer"
   ...     schema="z3ext.content.TESTS.IMyContainer"
   ...     description="Simple container type." /&gt;
   ... &lt;/configure&gt;""", context)

   &gt;&gt;&gt; ctContainer = component.getUtility(interfaces.IContentType, 'myContainer')

Unbound container can't contain any content

   &gt;&gt;&gt; list(ctContainer.listContainedTypes())
   []

   &gt;&gt;&gt; container = MyContainer('Container')

   &gt;&gt;&gt; bctContainer = ctContainer.__bind__(container)
   &gt;&gt;&gt; [ct.name for ct in bctContainer.listContainedTypes()]
   [u'myContent', u'myContainer']

   &gt;&gt;&gt; content = ctContent.create('Title')

We can't add content with unbound content type

   &gt;&gt;&gt; ctContent.add(content, 'test-content')
   Traceback (most recent call last):
   ...
   Unauthorized: Can't create '' instance

   &gt;&gt;&gt; bctContent = ctContent.__bind__(container)
   &gt;&gt;&gt; addedContent = bctContent.add(content, 'test-content')
   &gt;&gt;&gt; addedContent.__name__
   u'test-content'

   &gt;&gt;&gt; container[u'test-content'] is content
   True

But if conten type not in container content type types listing we won't 
able to add content.

   &gt;&gt;&gt; interface.directlyProvides(ctContent, interfaces.IInactiveType)
   &gt;&gt;&gt; t = sm.unregisterUtility(ctContent, interfaces.IActiveType, ctContent.name)
   
   &gt;&gt;&gt; [ct.name for ct in bctContainer.listContainedTypes()]
   [u'myContainer']

   &gt;&gt;&gt; content = ctContent.create(u'Title')
   
   &gt;&gt;&gt; addedContent = bctContent.add(content, 'test-content2')
   Traceback (most recent call last):
   ...
   InvalidItemType: ...


ContentType Type
----------------

We can use any number of types in type attribute of directive. 
By default package defines some types.

IInactiveType - for inactive types, this type can't be added to any container
also if we won't use 'factory' then content type marked as inactive automaticly

   &gt;&gt;&gt; ct = component.getUtility(interfaces.IContentType, 'myContent')
   &gt;&gt;&gt; interfaces.IInactiveType.providedBy(ct)
   True

   &gt;&gt;&gt; [ct.name for ct in bctContainer.listContainedTypes()]
   [u'myContainer']


IActiveType - for content that can be added to any content container

   &gt;&gt;&gt; class IContent1(interfaces.IItem):
   ...     pass

   &gt;&gt;&gt; class Content1(item.Item):
   ...     interface.implements(IContent1)

   &gt;&gt;&gt; context = xmlconfig.string("""
   ... &lt;configure xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="z3ext"&gt;
   ...   &lt;z3ext:content
   ...     name="content1"
   ...     title="content1"
   ...     schema="z3ext.content.TESTS.IContent1"
   ...     class="z3ext.content.TESTS.Content1"
   ...     type="z3ext.content.interfaces.IActiveType"
   ...     description="Simple content type." /&gt;
   ... &lt;/configure&gt;""", context)

   &gt;&gt;&gt; [ct.name for ct in bctContainer.listContainedTypes()]
   [u'myContainer', u'content1']


`IExplicitlyAddable` - if content type is explicitly addable then it can be added 
only to container that explicitly contains content type

   &gt;&gt;&gt; class IContent2(interfaces.IItem):
   ...     pass

   &gt;&gt;&gt; class Content2(item.Item):
   ...     interface.implements(IContent2)

   &gt;&gt;&gt; context = xmlconfig.string("""
   ... &lt;configure xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="z3ext"&gt;
   ...   &lt;z3ext:content
   ...     name="content2"
   ...     title="content2"
   ...     schema="z3ext.content.TESTS.IContent2"
   ...     class="z3ext.content.TESTS.Content2"
   ...     type="z3ext.content.tests.ITestContentType
   ...           z3ext.content.interfaces.IExplicitlyAddable"
   ...     description="Simple content type." /&gt;
   ... &lt;/configure&gt;""", context)

   &gt;&gt;&gt; [ct.name for ct in bctContainer.listContainedTypes()]
   [u'myContainer', u'content1']

Now let's add content type to precondition, it is the same if we use
`contains="mypackage.interface.IMyType"`

   &gt;&gt;&gt; precondition = component.queryUtility(
   ...     constraints.IItemTypePrecondition, bctContainer.name)
   &gt;&gt;&gt; precondition.ifaces = precondition.ifaces + (tests.ITestContentType, )

   &gt;&gt;&gt; [ct.name for ct in bctContainer.listContainedTypes()]
   [u'myContainer', u'content1', u'content2']


=======
CHANGES
=======

0.17.1 (2008-10-15)
-------------------

- Fix available list content types


0.17.0 (2008-10-15)
-------------------

- Prepare for removing auto generating content type maker interfaces.

- `contenttype` attribute is makrer interface for content type.

- `ctclass` custom content type implementation


0.16.0 (2008-10-08)
-------------------

- Use 'contents.html' link for content in contents view

- If container contains index.html content show it instead of listing

- Added IRenameNotAllowed marker interface

- Added container contents ordering

- Use z3ext.content i18n domain for transaltions

- Use zc.copy for content copy


0.15.0 (2008-08-28)
-------------------

- Added IPortalType,IActivePortalType types

- Using content schema for content creation

- Added short name validation for add/edit forms


0.14.3 (2008-08-13)
-------------------

- Use new pageelement api

- Added rename field to content edit form


0.14.2 (2008-08-07)
-------------------

- Fixed content creation, if content class doesn't have__init__ 

- Added `addform` attribute for z3ext:content directive,
  it allow use custom add form


0.14.1 (2008-08-05)
-------------------

- Fixed container __delitem__

- Fixed ContentType.create method

- Tests updated


0.14.0 (2008-08-04)
-------------------

- IItem is optional now

- Custom `breadcrumb` for content objects

- Added support for ordered containers


0.13.2 (2008-07-28)
-------------------

- Fixed edit form


0.13.1 (2008-07-24)
-------------------

- Added 'cancel' button to edit form


0.13.0 (2008-05-26)
-------------------

- Moved content actions to z3ext.ui.contentactions

- Moved content byline to to z3ext.ui.contentbyline

- Use viewlet for rendering content layout


0.12.0 (2008-04-08)
-------------------

- Added content actions


0.11.4 (2008-04-01)
-------------------

- Code cleanup


0.11.3 (2008-03-17)
-------------------

- Use z3ext.contextlayout for context


0.11.2 (2008-02-28)
-------------------

- Use z3c.autoinclude


0.11.1 (2008-02-25)
-------------------

- Code cleanup


0.11 (2008-02-20)
-----------------

- Replace zope.formlib with z3c.form


0.10.2 (2008-02-18)
-------------------

- Removed `rwproperty.py` from package

- Fixed bug with `View context` link in context information

- Added default `adapter` to IContentAdding

- Added `getContentType` to IContentAdding interface
  returns bound IContentType object

- Added viewlet structure for content view

- Added viewlet structure for content byline


0.10.1 (2008-02-12)
-------------------

- Move some code to z3ext.contentextensions package


0.10 (2008-02-04)
-----------------

- Rename 'for' to 'schema' for z3ext:content directive


0.9.1 (2008-02-02)
------------------

- Fixed missing import


0.9.0 (2008-02-01)
------------------

- Initial release.</description>
<homepage rdf:resource="http://z3ext.net/" />
<maintainer><foaf:Person><foaf:name>Nikolay Kim</foaf:name>
<foaf:mbox_sha1sum>d2ae7e827893a4b491ceed859306c037152b761c</foaf:mbox_sha1sum></foaf:Person></maintainer>
<release><Version><revision>0.17.1</revision></Version></release>
</Project></rdf:RDF>