Component Parts
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 |

Author: