How to programatically control an object's add-menu list of allowed content types?
I would like pragmatically to control individual objects' add-menu list of allowed content types.
I am building a collection of content types with archgenxml. In one case, I have a simulation class composed of a RangeBase class which has three realizations, valueRange, vectorRange and uniformRange. A simulation can contain exactly one range, i.e., RangeBase's multiplicity is one, so a simulation's add-menu should offer either all three range types or none at all.
To achieve this, I thought to subscribed to the IObjectInitializedEvent and IObjectRemovedEvent events; placing their respective handlers, initializedHook and removedHook, in the RangeBase class. The handlers would solicit an object's list of locally allowed types and remove or add the three ranges accordingly. After perusing the Plone's 'Community Developer Documentation', I thought the initializedHook code might look something like this:
# Set allowed content types
from Products.ATContentTyp开发者_运维问答es.lib import constraintypes
def initializedHook(obj, event):
# Get this range's parent simulation
parent = obj.aq_parent
# Enable constraining
parent.setConstrainTypesMode(constraintypes.ENABLED)
# Remove the three ranges
allowedTypes = parent.getLocallyAllowedTypes()
ranges = ('valueRange','vectorRange','uniformRange')
for range in ranges:
allowedTypes.remove(range)
# Tweak the menu
parent.setLocallyAllowedTypes(allowedTypes)
parent.setImmediatelyAddableTypes(allowedTypes)
Unfortunately, my simulation class has none of these functions.
Is there an adaptor that will provide my simulation class with this functionality, or are there other altogether different approaches to achieve the desired menu behaviour? Any suggestions would be appreciated.
It is possible.
I believe you need to override getLocallyAllowedType()
http://svn.plone.org/svn/collective/Products.ATContentTypes/trunk/Products/ATContentTypes/lib/constraintypes.py
AT was written time before adapters, so AT is not using it.
I suggest you could also update the documentation regarding this... it is pretty common use case.
http://web.archive.org/web/20101010142032/http://collective-docs.plone.org/content/creating.html
After several unsuccessful attempts at tweaking _allowedTypes(), I followed the last suggestion at http://plone.org/documentation/kb/restrict-addable-types and customized getNotAddableTypes.py. My customization merely lists a folder's contents filtering for the three ranges. If the resulting array is not empty, I add the three range types to the list:
# customize this script to filter addable portal types based on
# context, the current user or other criteria
ranges = []
ranges = context.listFolderContents(contentFilter={'portal_type':
('VectorRange','ValueRange','UniformRange')})
return {True: ('Favorite', 'VectorRange', 'ValueRange', 'UniformRange'),
False: ('Favorite')}[len(ranges)]
See the last post here for two possibilities: http://plone.293351.n2.nabble.com/Folder-constraints-not-applicable-to-custom-content-types-td6073100.html
The method
foo.getLocallyAllowedTypes()
gives back a tuple, that you just have to copy / filter into another tuple / list, because it's immutable.
allowed_types = parent.getLocallyAllowedTypes()
filtered_types = []
for v in allowed_types:
if not v in ranges:
filtered_types.append(v)
Then you can just give that tuple to the setter method
parent.setLocallyAllowedTypes(filtered_types)
and your're done. But if you want to access the parent during object creation to restrict content types of the folder, you creating the object in, you can hook up in at_post_create_script() and manage_beforeDelete() from BaseObject. This works great for me, restricting the number of specific content types to a folder and also corrects the AllowedTypes when the object gets deleted.
精彩评论