Commit 7447262a authored by Jérome Perrin's avatar Jérome Perrin

Extends Types Tool to support multiple types providers.

A type provider is a container for type informations, by default we only have
portal_types, but other types providers can be registered.



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@35109 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 9f3e7e53
...@@ -21,14 +21,26 @@ from Acquisition import aq_base ...@@ -21,14 +21,26 @@ from Acquisition import aq_base
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from OFS.Folder import Folder as OFSFolder from OFS.Folder import Folder as OFSFolder
import transaction import transaction
from Products.CMFCore import TypesTool as CMFCore_TypesTool from Products.CMFCore import TypesTool as CMFCore_TypesToolModule
from Products.ERP5Type.Tool.BaseTool import BaseTool from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Type.ERP5Type import ERP5TypeInformation from Products.ERP5Type.ERP5Type import ERP5TypeInformation
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from zLOG import LOG, WARNING, PANIC from zLOG import LOG, WARNING, PANIC
from Products.ERP5Type.interfaces import ITypeProvider, ITypesTool
class TypesTool(BaseTool, CMFCore_TypesTool.TypesTool):
CMFCore_TypesTool = CMFCore_TypesToolModule.TypesTool
class TypeProvider(BaseTool, CMFCore_TypesTool):
"""Provides portal content types
"""
zope.interface.implements(ITypeProvider)
_MARKER = []
class TypesTool(TypeProvider):
"""Provides a configurable registry of portal content types """Provides a configurable registry of portal content types
""" """
id = 'portal_types' id = 'portal_types'
...@@ -36,9 +48,40 @@ class TypesTool(BaseTool, CMFCore_TypesTool.TypesTool): ...@@ -36,9 +48,40 @@ class TypesTool(BaseTool, CMFCore_TypesTool.TypesTool):
portal_type = 'Types Tool' portal_type = 'Types Tool'
allowed_types = () allowed_types = ()
zope.interface.implements(ITypesTool)
# TODO: UI to configure this is missing
type_provider_list = ( 'portal_types', )
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
def listTypeInfo(self, container=None):
"""List type information from all providers
"""
listTypeInfo = CMFCore_TypesTool.listTypeInfo
type_info_list = []
for provider in self.type_provider_list:
provider_value = getattr(self, provider, None)
if provider_value is not None:
type_info_list.extend(
listTypeInfo(provider_value, container=container))
return type_info_list
def _getOb(self, id, default=_MARKER):
"""Get a type information from a provider
"""
_getOb = CMFCore_TypesTool._getOb
for provider in self.type_provider_list:
provider_value = getattr(self, provider, None)
if provider_value is not None:
ob = _getOb(provider_value, id, default=default)
if ob is not default:
return ob
if ob is _MARKER:
raise AttributeError, id
return ob
security.declarePrivate('getActionListFor') security.declarePrivate('getActionListFor')
def getActionListFor(self, ob=None): def getActionListFor(self, ob=None):
"""Return all actions applicable to the object""" """Return all actions applicable to the object"""
...@@ -238,4 +281,6 @@ class OldTypesTool(OFSFolder): ...@@ -238,4 +281,6 @@ class OldTypesTool(OFSFolder):
return OFSFolder.__of__(self, parent) return OFSFolder.__of__(self, parent)
return UnrestrictedMethod(base_self._migrateTypesTool)(parent) return UnrestrictedMethod(base_self._migrateTypesTool)(parent)
CMFCore_TypesTool.TypesTool = OldTypesTool # Change the CMFCore's TypesTool to automatically migrate to ERP5Type's
# TypesTool
CMFCore_TypesToolModule.TypesTool = OldTypesTool
...@@ -10,3 +10,4 @@ from category_access_provider import ICategoryAccessProvider ...@@ -10,3 +10,4 @@ from category_access_provider import ICategoryAccessProvider
from value_access_provider import IValueAccessProvider from value_access_provider import IValueAccessProvider
from constraint import IConstraint from constraint import IConstraint
from role_provider import ILocalRoleAssignor, ILocalRoleGenerator from role_provider import ILocalRoleAssignor, ILocalRoleGenerator
from types_tool import ITypesTool, ITypeProvider
##############################################################################
#
# Copyright (c) 2010 Nexedi SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""Types Tool Interfaces.
"""
from zope.interface import Interface
from zope.interface import Attribute
try:
from Products.CMFCore.interfaces import ITypesTool as ICMFCoreTypesTool
except ImportError:
# on CMF 1.5, this interface is generated by Five, and is not available at
# this point
class ICMFCoreTypesTool(Interface):
pass
class ITypesTool(ICMFCoreTypesTool):
"""ERP5Type's types tool.
ERP5Type's types tool extends CMF types tool, by looking up requested types
into registered types providers.
"""
type_provider_list = Attribute('type_provider_list',
'List of ids of types providers')
class ITypeProvider(ICMFCoreTypesTool):
"""A type provider contains type information, and conforms to CMF's
TypesTool interface, especially listTypeInfo and getTypeInfo methods.
"""
...@@ -147,13 +147,13 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor): ...@@ -147,13 +147,13 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor):
return str(randint(-10000000,100000000)) return str(randint(-10000000,100000000))
def getTemplateTool(self): def getTemplateTool(self):
return getattr(self.getPortal(), 'portal_templates', None) return getattr(self.portal, 'portal_templates', None)
def getCategoryTool(self): def getCategoryTool(self):
return getattr(self.getPortal(), 'portal_categories', None) return getattr(self.portal, 'portal_categories', None)
def getTypeTool(self): def getTypeTool(self):
return getattr(self.getPortal(), 'portal_types', None) return getattr(self.portal, 'portal_types', None)
# Here are the tests # Here are the tests
def testHasTemplateTool(self): def testHasTemplateTool(self):
...@@ -2735,6 +2735,43 @@ class TestPropertySheet: ...@@ -2735,6 +2735,43 @@ class TestPropertySheet:
self.assertNotEquals(None, method) self.assertNotEquals(None, method)
self.assertTrue(method()) self.assertTrue(method())
def test_type_provider(self):
from Products.ERP5Type.Tool.TypesTool import TypeProvider
class DummyTypeProvider(TypeProvider):
id = 'dummy_type_provider'
# portal_type = 'Dummy Type Provider'
self.portal._setObject('dummy_type_provider', DummyTypeProvider())
types_tool = self.portal.portal_types
# register our dummy type provider
types_tool.type_provider_list = types_tool.type_provider_list + (
'dummy_type_provider',)
# types created in our type provider are available
dummy_type = self.portal.dummy_type_provider.newContent(
portal_type='Base Type',
id='Dummy Type',
type_factory_method_id='addFolder', )
# our type is available from types tool
self.assertNotEquals(None, types_tool.getTypeInfo('Dummy Type'))
self.assertTrue('Dummy Type' in [ti.getId() for ti in
types_tool.listTypeInfo()])
# not existing types are not an error
self.assertEquals(None, types_tool.getTypeInfo(self.id()))
# we can create instances from our type provider
container = self.portal.newContent(portal_type='Folder', id='test_folder')
dummy_instance = container.newContent(portal_type='Dummy Type')
# and use generated accessors on them
dummy_type.edit(type_property_sheet_list=('Reference', ))
dummy_instance.setReference('test')
self.assertEquals('test', dummy_instance.getReference())
class TestAccessControl(ERP5TypeTestCase): class TestAccessControl(ERP5TypeTestCase):
# Isolate test in a dedicaced class in order not to break other tests # Isolate test in a dedicaced class in order not to break other tests
# when this one fails. # when this one fails.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment