I should expand on this more, but here’s a quick note about something I just did in a project I’m working on that may help some other people:
You know that Add… menu in the green bar when you have edit privileges on a page (I think the actual permission is ‘Modify portal content’)?
Have you ever wanted to replace the default call to portal_factory, via the createObject script with something else? Maybe a custom browser view that will create an object or give the user something else to do? (in my case it was ‘create a contact’ or ‘associate some existing contacts’).
Trying to use the five tag in zcml doesn’t work (it does work, however, to add new items to the display menu).
This does (at least in plone 4.0+, should also apply to 3.5). Given a standard plone egg-based product called my.product:
my/product, add the following:
- a menu module, I used a package, you can just use
<configure xmlns="http://namespaces.zope.org/zope" xmlns:five="http://namespaces.zope.org/five" xmlns:i18n="http://namespaces.zope.org/i18n" xmlns:gs="http://namespaces.zope.org/genericsetup" xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="blitzen.services"> <browser:menu id="plone_contentmenu_factory" title="The 'add' menu - allows the user to add new content items in the context" class=".menu.MyFactoriesMenu" /> </configure>
from plone.app.contentmenu.menu import FactoriesMenu, FactoriesSubMenuItem class MyFactoriesMenu(FactoriesMenu): """ Overload factories menu to do fancy stuff with adding new contacts """ def getMenuItems(self, context, request): # menuitems is a list of tal-friendly dictionaries menuitems = super(MyFactoriesMenu, self).getMenuItems(context, request) # we only want to pull these contact switcheroo shenanagians # if we're on a workspace object if context.portal_type != 'Workspace': return menuitems new_items =  for item in menuitems: if item.get('id', False) == 'Contact': new_item = item.copy() new_item['action'] = "%s/@@new_contact" % (context.absolute_url()) new_items.append(new_item) else: new_items.append(item) return new_items
There you go. Restart Zope and it should be using your menu items class instead of Plone’s. You can do whatever you want in there, change the order of the items, remove some, inject new ones, etc. See
configure.zcml file for more explaination, and the
FactoriesMenu class for more information about what the list of dictionaries returned by
getMenuItems is expecting.
One note: menus are aggressively cached in plone, so you might have to restart the app server where you’d normally just use
One other note: there are adapters you can override to do full-blown customizations. This approach seems a bit weird to me but I think it’s sound for the use case (I just want to override the createObject link in the menu).