How to override Plone's display menu for special case content?
To get a one-off view on a Plone folder I do something like this (not all code shown):
In configure.zcml
:
<!-- Marker interface. Set this on the folder through the ZMI
interfaces tab.
-->
<interface interface=".interfaces.IMySpecialFolder" />
In browser/configure.zcml
:
<!-- Special case view. Set as the folder's view through the ZMI
properties tab (layout property).
-->
<browser开发者_StackOverflow:page
for="..interfaces.IMySpecialFolder"
name="special"
template="special.pt"
permission="zope2.View"
/>
This works great, but I would like to control the folder's display menu to list only my special case view. I can add it, and it shows up only on my marked folder, but I have to change the site-wide ATFolder FTI.
In browser/configure.zcml
:
<include package="plone.app.contentmenu" />
<browser:menuItem
for="..interfaces.IMySpecialFolder"
menu="plone_displayviews"
title="Special view"
action="@@special"
description="Special case folder view"
/>
In profiles/default/types/Folder.xml
:
<?xml version="1.0"?>
<object name="Folder">
<property name="view_methods" purge="False">
<element value="special"/>
</property>
</object>
Of course I cannot remove the existing available view methods without affecting every folder on the site.
Is there a way to do this one-off display menu tweaking without changing a content type's FTI?
Actually, it seems like this problem has been tackled before. p4a.z2utils patches CMFDynamicViewFTI
to get the list of available views from an IDynamicallyViewable
adapter lookup. (dateable.chronos uses this mechanism for its folder calendar views). So my question becomes:
Is there a way to do this one-off display menu tweaking without changing a content type's FTI and without patching Plone?
The plone display menu builder uses ISelectableBrowserDefault
to get available options in the Display menu (see
http://dev.plone.org/plone/browser/plone.app.contentmenu/trunk/plone/app/contentmenu/menu.py#L220)
So I think (but I haven't tried this) that if you define an adapter for a more specific interface (in your case IMySpecialFolder
) that provides the Products.CMFDynamicViewFTI.interface.ISelectableBrowserDefault
it should work.
The adapter should have the methods required by plone.app.contentmenu.menu.DisplayMenu
above.
Answering my own question, I've realised that the most straightforward way to achieve one-off folder views is to follow the pattern Plone itself applies in the Members
folder: a PythonScript index_html
that calls the custom view, e.g.
member_search=context.restrictedTraverse('member_search_form')
return member_search()
Products.CMFPlone
illustrates how to setup such a PythonScript with a GenericSetup import handler.
In retrospect I realise I didn't need the marker interface in my question scenario. It's not necessary here in the answer either.
Note that this solution doesn't result in "the folder's display menu listing only my special case view" as I asked, but does away with the display menu altogether. I'm fine with that.
One way you could have solved it is using traversalhook to register menu items, or in this case, unregister menu items, or register menu items with conditions that make them not appear. With the traversal hook you can use a marker interface to make it just happen in a certain folder, subsection or page. You can see where we implemented similar code here
https://github.com/collective/collective.listingviews/blob/master/src/collective/listingviews/browser/views/controlpanel.py#L105
In this case we just wanted to register new display menu items dynamically based on control panel configuration.
精彩评论