Component Parts

« Return to page index

Plone Theme Reference

1. Interfaces and why they matter

Interfaces are a bit techie and something a non-developer would probably rather not think about. However, they are an important part of component wiring, so it is as well to know a bit about what they are and do.

Interfaces as Markers

ZCML attributes often refer to interfaces rather than actual classes - for instance the example below wires up the presentation viewlet for content types that have the IATDocument interface.

<browser:viewlet
      name="plone.presentation"
      for="Products.ATContentTypes.interface.IATDocument"
      manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"
      class=".presentation.PresentationViewlet"
      permission="zope2.View"
      />

In effect this is saying that the presentation viewlet is available for any content type which is ATDocument-like or behaves like an ATDocument. So, in this case, the interface is a marker.

The convenience of this is that a content type can have one (or more) interfaces, and several content types can share the same one. If you develop a new content type and mark it with the IATDocument interface, you can use this presentation viewlet with it - no extra wiring required.

Components and Interfaces

Components themselves can be marked with an interface - the technical term is "provides". Note that in the presentation viewlet example, the viewlet manager is referred to by its interface, not its name:

 manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"

To track down the actual component, look in the configure.zcml file in the same directory as the interfaces. For instance, in plone/app/layout/viewlets/configure.zcml you'll see the interface has been wired up with a Python class to create a viewlet manager component:

      <browser:viewletManager
        name="plone.abovecontentbody"
        provides=".interfaces.IAboveContentBody"
        permission="zope2.View"
        class="plone.app.viewletmanager.manager.OrderedViewletManager"
        />

How to spot an interface

It is usually fairly easy to spot a reference to an interface. By convention, their names will be prefixed with an "I", and they will live in an interface or interfaces namespace. If you investigate interfaces.py or interface.py in any egg or product, you won't find very much code, but you'll often find useful information – effectively it is documentation about what a component providing (i.e. marked by) that interface should do. For example:

class IAboveContentBody(IViewletManager):
    """A viewlet manager that sits above the content body in view templates    """

If you've used the plone3_theme paster template, you'll find you have a ready-made interfaces.py file to which you can add your own interfaces if you need to create them.

2. Python Classes

You'll have noticed that Python classes are often part of the wiring of Components, and you will find that you can't really avoid understanding a little bit about them, particularly if you want to make your own viewlets.

Having to deal with something as advanced as Python classes can be daunting for the non-developer. The good news is that using Python classes will be more a case of copying and changing little bits of code than writing anything from scratch.

What's a Class?

It's best to think of a class as a discrete piece of code containing a collection of methods ('actions' of some sort) and attributes ('variables' which can hold a value).

In the case of components, the main purpose of a class is to compute the pieces of information a component needs to display. The class for the logo viewlet is a good example. You can find it in:

  • [your egg location]/plone/app/layout/viewlets/common.py - look for LogoViewlet

After a bit of preparatory work, the LogoViewlet class first finds out the name of the image that is to be used for the logo (and is defined in the base_properties property sheet):

logoName = portal.restrictedTraverse('base_properties').logoName

Then it works out the logo's vital statistics, size, alt text etc and turns this into an HTML anchor tag:

self.logo_tag = portal.restrictedTraverse(logoName).tag()

Finally, just in case you might need it, it looks up the title of the site:

self.portal_title = self.portal_state.portal_title()

In the page template associated with this viewlet you can get hold of this information (self.logo_tag, self.portal_title) using the variable "view":

<img src="logo.jpg" alt=""
         tal:replace="structure view/logo_tag" />

Do I have to use Classes?

Viewlets tend to be wired up with a Python class which points to a template. So, even though you might only want to create a new template, you'll find that you have to write a class to point to your new template. The Elements section of this manual should help you by giving you a snippet of code for each element to copy and paste into your own product.

Here's an example. The standard logo template doesn't actually make use of view/portal_title. So if you wanted to incorporate this into your logo in some way, then you would need to write your own template and then also your own class:

from plone.app.layout.viewlets.common import LogoViewlet
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

class [your class name](LogoViewlet):
    render = ViewPageTemplateFile('[your template name]')
  • First, pull in ("import") all the bits and pieces with which to build your class using from ….. import …… .

  • Next, define your class. The important thing here is to base it on a pre-existing class so that you don't have to start from scratch. Put the name of the pre-existing class in brackets after your class name (make sure that you've imported it first). Don't forget the colon!
  • Finally, rewrite any of the methods or attributes you need. Here, we've just rewritten the render method to display our own template.

Note: indenting is very important in Python code, the convention is to use four spaces (rather than a tab). If you are having problems, double check the indentation first.

If you're feeling brave or want to know more, a straightforward introduction is here:


3. Permission

The permission attribute can be used to restrict visibility of a component.

When a user logs in to a site, they will be given a role ('manager' or 'editor' for instance). This role is, effectively, a set of permissions, giving them particular rights over particular aspects of the site.

To find out more about permissions consult the Understanding Permissions and Security Tutorial:

In the case of components, the permission attribute allows the site to decide whether a user has a right to see, or interact with a component. Most viewlets have the permission Zope2.View or Zope2.Public, which are permissions assigned to everyone, even anonymous visitors. However, look at the Lock Info viewlet:

<browser:viewlet
        name="plone.lockinfo"
        manager=".interfaces.IAboveContent"
        class="plone.locking.browser.info.LockInfoViewlet"
        permission="cmf.ModifyPortalContent"
        for="plone.locking.interfaces.ITTWLockable"
        />

By using cmf.ModifyPortalContent, this viewlet is restricted only to those who have the right to edit content (those who don't wouldn't be interested in whether an item was locked or not).

The list of available permissions is buried rather deeply in the Five product which comes with your installation of Zope - look in permissions.zcml for the most up-to-date list.

 

zope2.Public

Public, everyone can access

zope2.Private

Private, only accessible from trusted code

zope2.AccessContentsInformation

Access contents information

zope2.ChangeImagesFiles

Change Images and Files

zope2.ChangeConfig

Change configuration

zope2.ChangePermissions

Change permissions

zope2.CopyOrMove

Copy or Move

zope2.DefinePermissions

Define permissions

zope2.DeleteObjects

Delete objects

zope2.FTPAccess

FTP access

zope2.ImportExport

Import/Export objects

zope2.ManageProperties

Manage properties

zope2.ManageUsers

Manage users

zope2.Undo

Undo changes

zope2.View

View

zope2.ViewHistory

View History

zope2.ViewManagementScreens

View management screens

zope2.WebDAVLock

WebDAV Lock items

zope2.WebDAVUnlock

WebDAV Unlock items

zope2.WebDAVAccess

WebDAV access

cmf.ListFolderContents

List folder contents

cmf.ListUndoableChanges

List undoable changes

cmf.AccessInactivePortalContent

Access inactive portal content

cmf.ManagePortal

Manage portal

cmf.ModifyPortalContent

Modify portal content

cmf.ManageProperties

Manage properties

cmf.ListPortalMembers

List portal members

cmf.AddPortalFolders

Add portal folders

cmf.AddPortalContent

Add portal content

cmf.AddPortalMember

Add portal member

cmf.SetOwnPassword

Set own password

cmf.SetOwnProperties

Set own properties

cmf.MailForgottonPassword

Mail forgotten password

cmf.RequestReview

Request review

cmf.ReviewPortalContent

Review portal content

cmf.AccessFuturePortalContent

Access future portal content