Actions¶
Description
Creating and using portal_actions mechanism
- Introduction
- Iterating through available actions
- Creating actions through-the-web
- Creating actions.xml by hand
- Action URLs
- Default action
- Content-type specific actions
- Toggling action visibility programmatically
- Visibility expressions
- Using actions in views and viewlets
- Tabs (sections)
- Custom action listings
- Different tabs per section/folder
- Copy, cut and paste
Introduction¶
Plone has concept of actions which refer the end user functionality associated with site or content objects:
- View, edit, sharing etc. are actions
- Sitemap is action
- Contact form is action
- Cut, copy, paste are actions
- Logged in menu is populated by actions
Actions are managed by
- portal_actions for generic actions
- portal_types for view, edit etc. actions and object default action... all actions which are tied to a particular content type and may vary by type
Iterating through available actions¶
Here is a page template example
<ul>
<tal:actions repeat="action python:context.portal_actions.listFilteredActionsFor(context)['portal_tabs']">
<li>
<a tal:attributes="href action/url; title action/title;" tal:content="action/title">
Action title
</a>
</li>
</tal:actions>
</ul>
Creating actions through-the-web¶
Visit portal_actions in ZMI.
Exporting and importing all portal_actions¶
You can transfer action configuration from a Plone site to another using GenericSetup export/import XML. You can also do this to generate XML from which you can cut out snippets for creating actions.xml by hand.
- Go to portal_setup
- Choose Export
- Choose actions
- Choose "Export selected steps" button at the end of the page
- ...and so on
Creating actions.xml by hand¶
Usually all actions are rewritten by site policy product using portal_actions import/export. Actions are in GenericSetup profile file default/profiles/actions.xml.
- actions.xml is exported from the development instance using portal_setup
- actions.xml is made part of the site policy product
Alternatively, if you are developing add-on product, you can add actions one-by-one by manually creating entries in actions.xml.
Example how to add an action to object actions:
<?xml version="1.0"?>
<object name="portal_actions" meta_type="Plone Actions Tool"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<object name="document_actions" meta_type="CMF Action Category">
<object name="sendto" meta_type="CMF Action" i18n:domain="plone">
<property name="title" i18n:translate="">Send this</property>
<property name="description" i18n:translate=""></property>
<property name="url_expr">string:$object_url/sendto_form</property>
<property name="icon_expr"></property>
<property name="available_expr">object/@@shareable</property>
<property name="permissions">
<element value="Allow sendto"/>
</property>
<property name="visible">True</property>
</object>
</object>
Example how to add actions to user menu, which is visible in the top right corner for logged in users (Plone 4):
<?xml version="1.0"?>
<object name="portal_actions" meta_type="Plone Actions Tool"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<object name="user" meta_type="CMF Action Category">
<object name="ora_sync" meta_type="CMF Action" i18n:domain="plone">
<property name="title" i18n:translate="">ORA</property>
<property name="description" i18n:translate="">ORA site synchronization status</property>
<property name="url_expr">string:${portal_url}/@@syncall</property>
<property name="icon_expr"></property>
<property name="available_expr"></property>
<property name="permissions">
<element value="Manage portal"/>
</property>
<property name="visible">True</property>
</object>
</object>
</object>
Reordering actions in actions.xml¶
Try using these attributes
- insert-after
- insert-before
They accept * and action name parameters.
Example:
<object name="sendto" meta_type="CMF Action" i18n:domain="plone" insert-before="*">
Action URLs¶
Actions are applied to objects by adding action name to url.
E.g.:
http://localhost:8080/site/page/view
for view action and:
http://localhost:8080/site/page/edit
for edit action.
Action can be also not related to document, like:
http://localhost:8080/site/sitemap
Default action¶
Default action is executed when the content URL is opened without any prefix.
Default action is defined in portal_types.
Default action can be dynamic - meaning that site editor may set it from Display menu. For more information see Dynamic Views.
Content-type specific actions¶
Content-type specific actions can be registered in portal_types. Actions are viewable and editable in Zope Management Interface under portal_types. After editing actions, content type XML can be exported and placed to your content type add-on product.
GenericSetup example file for content type "ProductCard" which has a new tab added next to view, edit, sharing, etc. File is located in profiles/default/types/ProductCard.xml.
<?xml version="1.0"?>
<object name="ProductCard"
meta_type="Factory-based Type Information with dynamic views"
i18n:domain="saariselka.app" xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<property name="title" i18n:translate="">Tuotekortti</property>
....
<alias from="(Default)" to="(dynamic view)" />
<alias from="edit" to="atct_edit" />
<alias from="sharing" to="@@sharing" />
<alias from="view" to="(selected layout)" />
<action title="View" action_id="view" category="object" condition_expr=""
url_expr="string:${object_url}/" visible="True">
<permission value="View" />
</action>
<action title="Edit" action_id="edit" category="object" condition_expr=""
url_expr="string:${object_url}/edit" visible="True">
<permission value="Modify portal content" />
</action>
<!-- Custom action code goes here. We add a new tab with title "Data" and
uri @@productdata_view which is a registered BrowserView for the content type.
-->
<action title="Data" action_id="productdata_view" category="object" condition_expr=""
url_expr="string:${object_url}/@@productdata_view" visible="True">
<permission value="Modify portal content" />
</action>
</object>
The corresponding BrowserView is registered as any other view in browser/configure.zcml:
<browser:page
for="*"
name="productdata_view"
class=".productdataview.ProductDataView"
template="productdataview.pt"
allowed_attributes="renderData"
permission="zope2.View"
/>
Toggling action visibility programmatically¶
Warning
This applies only for Plone 2.5. You should use actions.xml instead.
Example:
def disable_actions(portal):
""" Remove unneeded Plone actions
@param portal Plone instance
"""
# getActionObject takes parameter category/action id
# For ids and categories please refer to portal_actins in ZMI
actionInformation = portal.portal_actions.getActionObject("document_actions/rss")
# See ActionInformation.py / ActionInformation for available edits
actionInformation.edit(visible=False)
Visibility expressions¶
In portal_actions expression is used to determine whether an action is visible on a particular page.
Expression is "expression" field in actions.xml or "Expression" field in portal_actions.
Note
This check is just a visibility check. Users can still try to type the action by typing the URL manually. You need to do the permission level security check on the view providing the action.
For more information see expressions.
Condition examples¶
See in expressions.
Using actions in views and viewlets¶
Example:
context_state = getMultiAdapter((self.context, self.request),
name=u'plone_context_state')
# First argument is action category,
# we have custom "mobile_actions"
self.actions = context_state.actions().get('mobile_actions', None)
Tabs (sections)¶
Tabs are special actions
- Some of tabs are automatically generated from root level content items
- Some of tabs are manually added to portal_actions.portal_tabs
By default, they are shown as the top vertical navigation of Plone site.
Example how to generate tabs list:
def getSections(self):
"""
@return: tuple (selectedTabs, currentSelectedTab)
"""
context_state = getMultiAdapter((self.context, self.request),
name=u'plone_context_state')
actions = context_state.actions()
# Get CatalogNavigationTabs instance
portal_tabs_view = getMultiAdapter((self.context, self.request),
name='portal_tabs_view')
# Action parameter is "portal_tabs" by default, but can be other
portal_tabs = portal_tabs_view.topLevelTabs(actions=actions)
selectedTabs = self.context.restrictedTraverse('selectedTabs')
selected_tabs = selectedTabs('index_html',
self.context,
portal_tabs)
selected_portal_tab = selected_tabs['portal']
return (portal_tabs, selected_portal_tab)
Custom action listings¶
Example:
import Acquisition
from zope.component import getMultiAdapter
class Sections(base.Sections):
"""
"""
def update(self):
base.Sections.update(self)
context = Acquisition.aq_inner(self.context)
# IContextState view provides shortcut to get different action listings
context_state = getMultiAdapter((context, self.request), name=u'plone_context_state')
all_actions = context_state.keyed_actions() # id -> action mappings
mobile_site_actions = all_actions["mobile_site_actions"].values()
self.portal_tabs = mobile_site_actions
Different tabs per section/folder¶
You might want to have different actions for different site sections or folders.
Copy, cut and paste¶
These action are based on
OFS
Zope 2 package SimpleItem mechanisms. Plone specific event
handlers are used to update Plone related stuff like
portal_catalog
on move.
Plone internal clipboard relies on the presence of Zope 2
session (different from authentication session). Paste
action fails silenlty (is missing) if
_ZopeId
session cookie does not work correctly on your web server.