Commit 114aad17 authored by Julien Muchembled's avatar Julien Muchembled

Rewrite ERP5TypeInformation.getInstance* to reduce code duplication

* Move creation of temporary instances from Folder.newContent to
  ERP5TypeInformation.constructInstance.
* Use temporary object and PropertyHolder (if possible) to get list of
  categories and properties.
* Also rewrite
  TranslationProviderBase.updateInitialPropertyTranslationDomainDict

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30160 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 3caddcdf
...@@ -148,24 +148,15 @@ class FolderMixIn(ExtensionClass.Base): ...@@ -148,24 +148,15 @@ class FolderMixIn(ExtensionClass.Base):
'portal_trash' not in container.getPhysicalPath(): 'portal_trash' not in container.getPhysicalPath():
raise ValueError('Disallowed subobject type: %s' % portal_type) raise ValueError('Disallowed subobject type: %s' % portal_type)
# Use the factory even if the parent is already a temp object, type_info = pt.getTypeInfo(portal_type)
# like this we do not call the classic way, indeed, we do not if type_info is None:
# need to call init script, security settings on temp objects. raise ValueError('No such content type: %s' % portal_type)
if temp_object or temp_container:
type_info = pt.getTypeInfo(portal_type) new_instance = type_info.constructInstance(
if not type_info.factory or not type_info.factory.startswith('add'):
raise ValueError('Product factory for %s is invalid: %s' %
(portal_type, type_info.factory))
p = container.manage_addProduct[type_info.product]
m = getattr(p, 'newTemp' + type_info.factory[3:])
new_instance = m(new_id, container)
if hasattr(new_instance, '_setPortalTypeName'):
new_instance._setPortalTypeName(portal_type)
else:
pt.constructContent( type_name=portal_type,
container=container, container=container,
id=new_id, id=new_id,
created_by_builder=created_by_builder, created_by_builder=created_by_builder,
temp_object=temp_object or temp_container,
activate_kw=activate_kw, activate_kw=activate_kw,
reindex_kw=reindex_kw, reindex_kw=reindex_kw,
is_indexable=is_indexable is_indexable=is_indexable
...@@ -173,7 +164,6 @@ class FolderMixIn(ExtensionClass.Base): ...@@ -173,7 +164,6 @@ class FolderMixIn(ExtensionClass.Base):
# TODO :the **kw makes it impossible to create content not based on # TODO :the **kw makes it impossible to create content not based on
# ERP5TypeInformation, because factory method often do not support # ERP5TypeInformation, because factory method often do not support
# keywords arguments. # keywords arguments.
new_instance = container[new_id]
if kw != {} : new_instance._edit(force_update=1, **kw) if kw != {} : new_instance._edit(force_update=1, **kw)
if immediate_reindex: new_instance.immediateReindexObject() if immediate_reindex: new_instance.immediateReindexObject()
......
...@@ -30,6 +30,7 @@ from Products.CMFCore.Expression import Expression ...@@ -30,6 +30,7 @@ from Products.CMFCore.Expression import Expression
from Products.CMFCore.exceptions import AccessControl_Unauthorized from Products.CMFCore.exceptions import AccessControl_Unauthorized
from Products.CMFCore.utils import _checkPermission from Products.CMFCore.utils import _checkPermission
from Products.ERP5Type import interfaces, Constraint, Permissions, PropertySheet from Products.ERP5Type import interfaces, Constraint, Permissions, PropertySheet
from Products.ERP5Type.Base import getClassPropertyList
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Type.Utils import deprecated, createExpressionContext from Products.ERP5Type.Utils import deprecated, createExpressionContext
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
...@@ -376,14 +377,24 @@ class ERP5TypeInformation(XMLObject, ...@@ -376,14 +377,24 @@ class ERP5TypeInformation(XMLObject,
return default return default
security.declarePublic('constructInstance') security.declarePublic('constructInstance')
def constructInstance( self, container, id, def constructInstance(self, container, id, created_by_builder=0,
created_by_builder=0, *args, **kw ): temp_object=0, *args, **kw ):
""" """
Build a "bare" instance of the appropriate type in Build a "bare" instance of the appropriate type in
'container', using 'id' as its id. 'container', using 'id' as its id.
Call the init_script for the portal_type. Call the init_script for the portal_type.
Returns the object. Returns the object.
""" """
if temp_object:
if not self.factory or not self.factory.startswith('add'):
raise ValueError('Product factory for %s is invalid: %s'
% (self.getId(), self.factory))
p = container.manage_addProduct[self.product]
m = getattr(p, 'newTemp' + self.factory[3:])
ob = m(id, container)
if hasattr(ob, '_setPortalTypeName'):
ob.portal_type = self.getId()
else:
# This is part is copied from CMFCore/TypesTool/constructInstance # This is part is copied from CMFCore/TypesTool/constructInstance
# In case of temp object, we don't want to check security # In case of temp object, we don't want to check security
if (not (hasattr(container, 'isTempObject') if (not (hasattr(container, 'isTempObject')
...@@ -418,7 +429,12 @@ class ERP5TypeInformation(XMLObject, ...@@ -418,7 +429,12 @@ class ERP5TypeInformation(XMLObject,
kw['created_by_builder'] = created_by_builder kw['created_by_builder'] = created_by_builder
getattr(ob, init_script)(*args, **kw) getattr(ob, init_script)(*args, **kw)
return ob return ob
def _getPropertyHolder(self):
ob = self.constructInstance(self, '', temp_object=1)
ob._aq_dynamic('id')
return ob.aq_portal_type[ob._aq_key()]
security.declarePrivate('updatePropertySheetDefinitionDict') security.declarePrivate('updatePropertySheetDefinitionDict')
def updatePropertySheetDefinitionDict(self, definition_dict): def updatePropertySheetDefinitionDict(self, definition_dict):
...@@ -451,61 +467,27 @@ class ERP5TypeInformation(XMLObject, ...@@ -451,61 +467,27 @@ class ERP5TypeInformation(XMLObject,
'getInstanceBaseCategoryList') 'getInstanceBaseCategoryList')
def getInstanceBaseCategoryList(self): def getInstanceBaseCategoryList(self):
""" Return all base categories of the portal type """ """ Return all base categories of the portal type """
# try to get categories from a temporary object if possible return list(self._getPropertyHolder()._categories)
module = self.getPortalObject().getDefaultModule(self.getId())
if module is not None:
return module.newContent(portal_type=self.getId(), temp_object=1).getBaseCategoryList()
# XXX The following does not return the list of all categories currently
# (as implementation does not follow exactly the accessor generation,
# like for Expression evaluation). Should be probably better to get
# the list from property holder and not from property sheet
# get categories from portal type
base_category_set = set(self.getTypeBaseCategoryList())
# get categories from property sheet
ps_list = [getattr(PropertySheet, p, None)
for p in self.getTypePropertySheetList()]
# from the property sheets defined on the class
m = Products.ERP5Type._m
if m.has_key(self.factory):
klass = m[self.factory].klass
if klass is not None:
from Products.ERP5Type.Base import getClassPropertyList
ps_list += getClassPropertyList(klass)
# XXX Can't return set to restricted code in Zope 2.8.
return list(base_category_set.union(category
for base in ps_list
for category in getattr(base, '_categories', ())))
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getInstancePropertyAndBaseCategoryList') 'getInstancePropertyAndBaseCategoryList')
def getInstancePropertyAndBaseCategoryList(self): def getInstancePropertyAndBaseCategoryList(self):
"""Return all the properties and base categories of the portal type. """ """Return all the properties and base categories of the portal type. """
return_set = set() # PropertHolder._properties doesn't contain 'content' properties.
ob = self.constructInstance(self, '', temp_object=1)
property_list = list(getattr(ob.__class__, '_properties', []))
self.updatePropertySheetDefinitionDict({'_properties': property_list})
for property_sheet in getClassPropertyList(ob.__class__):
property_list += property_sheet._properties
# get the property sheet list for the portal type return_set = set()
ps_list = [getattr(PropertySheet, p, None) for property in property_list:
for p in self.getTypePropertySheetList()] if property['type'] == 'content':
m = Products.ERP5Type._m for suffix in property['acquired_property_id']:
if m.has_key(self.factory): return_set.add(property['id'] + '_' + suffix)
klass = m[self.factory].klass else:
if klass is not None: return_set.add(property['id'])
from Products.ERP5Type.Base import getClassPropertyList for category in ob.getBaseCategoryList():
ps_list += getClassPropertyList(klass)
# get all properties from the property sheet list
for base in ps_list:
property_list = getattr(base, '_properties', None)
if property_list:
for property in property_list:
if property['type'] == 'content':
for suffix in property['acquired_property_id']:
return_set.add(property['id'] + '_' + suffix)
else:
return_set.add(property['id'])
# get base categories
for category in self.getInstanceBaseCategoryList():
return_set.add(category) return_set.add(category)
return_set.add(category + '_free_text') return_set.add(category + '_free_text')
...@@ -517,22 +499,8 @@ class ERP5TypeInformation(XMLObject, ...@@ -517,22 +499,8 @@ class ERP5TypeInformation(XMLObject,
def getInstancePropertyMap(self): def getInstancePropertyMap(self):
""" """
Returns the list of properties which are specific to the portal type. Returns the list of properties which are specific to the portal type.
We do this by creating a temp object at the root of the portal
and invoking propertyMap
""" """
# Access the factory method for temp object by guessing it return self.constructInstance(self, '', temp_object=1).propertyMap()
# according to ERP5 naming conventions (not very nice)
factory_method_id = self.factory.replace('add', 'newTemp', 1)
if not factory_method_id.startswith('newTemp'):
raise
factory_method = getattr(Products.ERP5Type.Document, factory_method_id)
id = "some_very_unlikely_temp_object_id_which_should_not_exist"
portal = self.getPortalObject()
portal_ids = portal.objectIds()
while id in portal_ids:
id = id + "d"
return factory_method(portal, id).propertyMap()
def _edit(self, *args, **kw): def _edit(self, *args, **kw):
""" """
......
...@@ -58,34 +58,18 @@ class TranslationProviderBase(object): ...@@ -58,34 +58,18 @@ class TranslationProviderBase(object):
""" """
property_domain_dict = {} property_domain_dict = {}
# get the property sheet list for the portal type for prop in self._getPropertyHolder()._properties:
ps_list = [getattr(PropertySheet, p, None) prop_id = prop['id']
for p in self.getTypePropertySheetList()] if prop.get('translatable') and prop_id not in property_domain_dict:
m = Products.ERP5Type._m domain_name = prop.get('translation_domain')
if m.has_key(self.factory): property_domain_dict[prop_id] = TranslationInformation(prop_id,
klass = m[self.factory].klass domain_name)
if klass is not None:
from Products.ERP5Type.Base import getClassPropertyList
ps_list += getClassPropertyList(klass)
# create TranslationInformation object for each property
for base in ps_list:
for prop in getattr(base, '_properties', ()):
prop_id = prop['id']
if prop.get('translatable') and prop_id not in property_domain_dict:
domain_name = prop.get('translation_domain')
property_domain_dict[prop_id] = TranslationInformation(prop_id,
domain_name)
original_property_domain_dict = getattr(aq_base(self), original_property_domain_dict = getattr(aq_base(self),
'_property_domain_dict', _MARKER) '_property_domain_dict', _MARKER)
original_property_domain_keys = original_property_domain_dict.keys()
property_domain_keys = property_domain_dict.keys()
property_domain_keys.sort()
original_property_domain_keys.sort()
# Only update if required in order to prevent ZODB from growing # Only update if required in order to prevent ZODB from growing
if original_property_domain_dict is _MARKER or\ if original_property_domain_dict is _MARKER or\
property_domain_keys != original_property_domain_keys: sorted(property_domain_dict) != sorted(original_property_domain_dict):
# Update existing dict # Update existing dict
property_domain_dict.update(original_property_domain_dict) property_domain_dict.update(original_property_domain_dict)
# And store # And store
......
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