Commit 7b8811c8 authored by Julien Muchembled's avatar Julien Muchembled

Revert [35537] and speed up contentValues by optimizing TypesTool.listContentTypes

[35537] was committed for performance reason, but it changed the behaviour of
Folder.contentValues

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@35908 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 04c300c5
...@@ -1431,16 +1431,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn, ...@@ -1431,16 +1431,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn,
def contentValues(self, *args, **kw): def contentValues(self, *args, **kw):
# Returns a list of documents contained in this folder. # Returns a list of documents contained in this folder.
# ( no docstring to prevent publishing ) # ( no docstring to prevent publishing )
portal_type_id_list = self._getTypesTool().listContentTypes()
filter_kw = kw.pop('filter', None) or {} filter_kw = kw.pop('filter', None) or {}
portal_type = kw.pop('portal_type', None) portal_type = kw.pop('portal_type', None)
if 'portal_type' in filter_kw: if 'portal_type' in filter_kw:
portal_type = filter_kw.pop('portal_type') portal_type = filter_kw.pop('portal_type')
if portal_type is None: if portal_type is None:
kw['portal_type'] = self._getTypesTool().listContentTypes() kw['portal_type'] = portal_type_id_list
else: else:
if isinstance(portal_type, str): if isinstance(portal_type, str):
portal_type = portal_type, portal_type = portal_type,
kw['portal_type'] = portal_type kw['portal_type'] = [x for x in portal_type if x in portal_type_id_list]
object_list = self.objectValues(*args, **kw) object_list = self.objectValues(*args, **kw)
if filter_kw: if filter_kw:
object_list = filter(ContentFilter(**filter_kw), object_list) object_list = filter(ContentFilter(**filter_kw), object_list)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
############################################################################## ##############################################################################
import imp, sys, warnings import imp, sys, warnings
from itertools import chain
import zope.interface import zope.interface
from Acquisition import aq_base from Acquisition import aq_base
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
...@@ -30,6 +31,47 @@ from zLOG import LOG, WARNING, PANIC ...@@ -30,6 +31,47 @@ from zLOG import LOG, WARNING, PANIC
from Products.ERP5Type.interfaces import ITypeProvider, ITypesTool from Products.ERP5Type.interfaces import ITypeProvider, ITypesTool
class ComposedObjectIds(object):
"""Sequence type used to iterate efficiently over a union of folders
Returned values are ids of contained objects.
This type should used instead of building a simple list from the concatenation
of multiple calls on objectIds.
Note this class even implements '__contains__', which makes:
'some_id' in ComposedObjectIds([container])
faster than:
'some_id' in container.objectIds()
XXX Is it only useful for TypesTool ?
If not, this should it be moved in another place, like ERP5Type.Utils
"""
__allow_access_to_unprotected_subobjects__ = 1
def __init__(self, container_list):
self._container_list = container_list
def __contains__(self, item):
for container in self._container_list:
if container.has_key(item):
return True
return False
def __iter__(self):
return chain(*[container.objectIds() for container in self._container_list])
def __len__(self):
return sum(map(len, self._container_list))
def __getitem__(self, item):
for container in self._container_list:
count = len(container)
if item < count:
return container.objectIds()[item]
item -= count
raise IndexError
CMFCore_TypesTool = CMFCore_TypesToolModule.TypesTool CMFCore_TypesTool = CMFCore_TypesToolModule.TypesTool
class TypeProvider(BaseTool, CMFCore_TypesTool): class TypeProvider(BaseTool, CMFCore_TypesTool):
...@@ -54,19 +96,32 @@ class TypesTool(TypeProvider): ...@@ -54,19 +96,32 @@ class TypesTool(TypeProvider):
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
def listContentTypes(self, container=None):
"""List content types from all providers
"""
if container is not None:
# XXX Slow legacy implementation. Is 'container_list' parameter useful ?
return CMFCore_TypesTool.listContentTypes(self, container)
object_list = [self]
_getOb = self.getPortalObject()._getOb
for provider in self.type_provider_list:
provider_value = _getOb(provider, None)
if provider_value:
object_list.append(provider_value)
return ComposedObjectIds(object_list)
def listTypeInfo(self, container=None): def listTypeInfo(self, container=None):
"""List type information from all providers """List type information from all providers
""" """
listTypeInfo = CMFCore_TypesTool.listTypeInfo listTypeInfo = CMFCore_TypesTool.listTypeInfo
type_info_list = listTypeInfo(self, container=container) type_info_list = listTypeInfo(self, container=container)
portal = self.getPortalObject() _getOb = self.getPortalObject()._getOb
for provider in self.type_provider_list: for provider in self.type_provider_list:
provider_value = portal._getOb(provider, None) provider_value = _getOb(provider, None)
if provider_value is not None: if provider_value is not None:
type_info_list.extend( type_info_list += listTypeInfo(provider_value, container=container)
listTypeInfo(provider_value, container=container))
return type_info_list return type_info_list
def _aq_dynamic(self, id): def _aq_dynamic(self, id):
"""Get a type information from a provider """Get a type information from a provider
""" """
......
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