############################################################################## # # Copyright (c) 2004 Philipp "philiKON" von Weitershausen # # This software is distributed under the terms of the Zope Public # License (ZPL) v2.1. # ############################################################################## """Vocabulary $Id$ """ from zope.interface.interface import Specification from zope.component.interfaces import IFactory from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary from zope.app import zapi from zope.app.content.interfaces import IContentType from zope.app.container.constraints import checkFactory def queryContentType(ifaces): """Out of an iterable of interfaces, find the one interface that is a content type Imagine we have a couple of interfaces, one of them is a content type: >>> from zope.interface import Interface, directlyProvides >>> class IFoo(Interface): ... pass >>> class IBar(Interface): ... pass >>> directlyProvides(IBar, IContentType) >>> class ISubbar(IBar): ... pass Now we throw two of them in a list: >>> ifaces = [IFoo, ISubbar] We expect queryContentType to tell us that IBar is the content type: >>> queryContentType(ifaces) is IBar True """ spec = Specification(ifaces) for iface in spec.__iro__: if IContentType.providedBy(iface): return iface return None class AddMenuContentTypesVocabulary(SimpleVocabulary): """Vocabulary of content type interfaces based on the browser add menu TODO: doctest """ def __init__(self, context): terms = [] menu_service = zapi.getService("BrowserMenu") menu_id = 'zope.app.container.add' # there can be several factories for one content type; we # really care about the content type, not the factory; we just # conveniently use the factory id as a token seen_types = {} for item in menu_service.getAllMenuItems(menu_id, context): if item.extra: token = item.extra.get('factory') if token: factory = zapi.getUtility(IFactory, token) content_type = queryContentType(factory.getInterfaces()) # don't continue if the add entry is not for a content type if not content_type: continue # check if this type of object can actually added here if not checkFactory(context, None, factory): continue if content_type in seen_types: # XXX this is not very i18n friendly seen_types[content_type][1] += ", " + item.title else: seen_types[content_type] = [token, item.title] terms = [SimpleTerm(content_type, token, title) for content_type, (token, title) in seen_types.iteritems()] super(AddMenuContentTypesVocabulary, self).__init__(terms)