Composer templates, IFormat and IFullFormatter

31 views
Skip to first unread message

Daniel Nouri

unread,
Jun 23, 2008, 8:10:22 AM6/23/08
to singing...@googlegroups.com
This post is about how formatting and presentation works in S&D. I've
had a longer chat with jensens today on IRC in #singing-dancing and I
realized that some of what's going on with the formatters can be
confusing.

First off, you might know that the items that go into a newsletter might
be either the document that a user clicks "send as newsletter" on, or
items collected automatically from the portal in a scheduled, automatic
newsletter, or both.

Formatters: More generic, but harder way
----------------------------------------

Now there's a couple of default formatters in S&D which may or may not
work for you. There's a formatter called "PloneCallHTMLFormatter".
This one is used for documents that the user sends out straight
(i.e. "send as newsletter" action). It'll format the document the same
way that you see it in Plone, that is you get the title, description,
and full body. We call this formatter a "full formatter", aka
"IFullFormatter". If you don't like how items are "full formatted" in
your newsletters, register another IFullFormatter, e.g. in your ZCML:

<adapter factory=".mymodule.MyATDocumentFormatter"
for="Products.ATContentTypes.interfaces.IATDocument
zope.publisher.interfaces.browser.IBrowserRequest"
provides="collective.dancing.interfaces.IFullFormatter"
name="html" />

With this formatter registered, you'll use your own formatter for Plone
documents ("IATDocument").

Then there's another type of formatters. These are used for items
collected through the Collector (think: Smart Folder) interface. For
these, you generally don't want a full representation, so let's call
these "standard formatters". S&D registers a generic standard formatter
for CMFCore's "IDublinCore" that renders only title, description, and a
link to the document. If you wanted to override this, you could
register, similar to our previous registration, in ZCML:

<adapter factory=".mymodule.MyATDocumentFormatter"
for="Products.ATContentTypes.interfaces.IATDocument
zope.publisher.interfaces.browser.IBrowserRequest"
provides="collective.singing.interfaces.IFormatItem"
name="html" />

Note that the only thing that changes here is the "provides" argument.
We're registering the same formatter that we used before for this other
brief format: IFormatItem.

Using a custom composer template: easier, but less generic way
--------------------------------------------------------------

Now if this all sounds too complicated to you and all you want is to
change directly the e-mail template and render all the items yourself
therein, you can! The default IComposer template [1] is quite simple.

You can override this template by subclassing from the default
HTMLComposer [2] and overriding the template attribute:

>>> from zope.app.pagetemplate.viewpagetemplatefile \
... import ViewPageTemplateFile
>>> from collective.dancing.composer import HTMLComposer
>>> class MyHTMLComposer(HTMLComposer):
... template = ViewPageTemplateFile('my-template.pt')

Then, in your installation script, or event handler, set your channel to
use this composer:

>>> my_channel = portal.portal_newsletters.channels['my-channel']
>>> my_channel.composers['html'] = MyHTMLComposer()

You can also use different stylesheets for different composers (they're
persistent):

>>> my_channel.composers['html'].stylesheet = """
... h1 { color: white; background: orange !important; }
... h2 { color: white; background: green !important; }"""

In your composer template, you can access all items, both formatted and
unformatted (i.e. straight Plone objects) through the "options/items"
variable, like this:

<ul>
<li tal:repeat="tuple options/items">
<a href=""
tal:define="raw_item python:tuple[1]"
tal:content="raw/Title"
tal:attributes="href raw/absolute_url">
Some document
</a>
</li>
</ul>

Of course, if you use this approach, your composer will be tied to the
type of items returned by your collector. The reason that IFormat and
IFullFormatter adapters exist is that you can use plug collectors with
arbitrary types into generic composers that only expect unicode strings.

In the future, we'll implement through the web editable templates for
composers, which will make customization even easier.


[1] http://dev.plone.org/collective/browser/collective.dancing/tags/0.4b3/collective/dancing/browser/composer-html.pt
[2] http://dev.plone.org/collective/browser/collective.dancing/trunk/collective/dancing/composer.py#L55


--
Daniel Nouri
http://danielnouri.org

Daniel Nouri

unread,
Aug 13, 2008, 9:52:52 AM8/13/08
to Singing & Dancing
There's a typo with the previous post in this thread. The ZCML
registrations are made for
Products.ATContentTypes.interfaces.IATDocument here, which is wrong.
They should be made for
Products.ATContentTypes.interface.document.IATDocument instead.

Thanks to Dan Jacka for pointing this out.

Daniel Nouri

unread,
Jun 23, 2009, 7:43:33 AM6/23/09
to Chris, singing...@googlegroups.com
On Tue, Jun 23, 2009 at 10:00 AM, Chris<christof...@gmail.com> wrote:
> On 23 Juni 2008, 14:10, Daniel Nouri <daniel.no...@gmail.com> wrote:
>> Using acustomcomposertemplate: easier, but less generic way
>> --------------------------------------------------------------
> ...

>> You can override this template by subclassing from the default
>> HTMLComposer [2] and overriding the template attribute:
> ...

>> Then, in your installation script, or event handler, set your channel to
>> use thiscomposer:
>>
>>   >>> my_channel = portal.portal_newsletters.channels['my-channel']
>>   >>> my_channel.composers['html'] = MyHTMLComposer()
> Which installation script would that be? The S&D installation script?
> An installation script of an add-on product I have created? Some other
> installation script?

The installation script of your product. This assumes that you set up
your newsletter channels programmatically on install.

> On the same theme, the event handlers would those be run when Plone is
> started, each time a channel is created, each time a channel is
> accessed, ...?

When event handlers are run depends on the type of event. If you're
handling a IObjectAdded event, then your handler is only run when that
object is added.


Daniel

Reply all
Reply to author
Forward
0 new messages