diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py index 8a60e6796ca6caa1fd333b0b98612c54f31d7107..e89827edeebd7a5cdc11aed9b7d36b11f446b8f1 100644 --- a/product/ERP5Type/Core/Folder.py +++ b/product/ERP5Type/Core/Folder.py @@ -148,24 +148,15 @@ class FolderMixIn(ExtensionClass.Base): 'portal_trash' not in container.getPhysicalPath(): raise ValueError('Disallowed subobject type: %s' % portal_type) - # Use the factory even if the parent is already a temp object, - # like this we do not call the classic way, indeed, we do not - # need to call init script, security settings on temp objects. - if temp_object or temp_container: - type_info = pt.getTypeInfo(portal_type) - 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, + type_info = pt.getTypeInfo(portal_type) + if type_info is None: + raise ValueError('No such content type: %s' % portal_type) + + new_instance = type_info.constructInstance( container=container, id=new_id, created_by_builder=created_by_builder, + temp_object=temp_object or temp_container, activate_kw=activate_kw, reindex_kw=reindex_kw, is_indexable=is_indexable @@ -173,7 +164,6 @@ class FolderMixIn(ExtensionClass.Base): # TODO :the **kw makes it impossible to create content not based on # ERP5TypeInformation, because factory method often do not support # keywords arguments. - new_instance = container[new_id] if kw != {} : new_instance._edit(force_update=1, **kw) if immediate_reindex: new_instance.immediateReindexObject() diff --git a/product/ERP5Type/ERP5Type.py b/product/ERP5Type/ERP5Type.py index 8d470379cc96de0fa49fd74fca5c03deb978e5a0..fa17a3ee30c17d234292705fd81b9c99572d17a6 100644 --- a/product/ERP5Type/ERP5Type.py +++ b/product/ERP5Type/ERP5Type.py @@ -30,6 +30,7 @@ from Products.CMFCore.Expression import Expression from Products.CMFCore.exceptions import AccessControl_Unauthorized from Products.CMFCore.utils import _checkPermission from Products.ERP5Type import interfaces, Constraint, Permissions, PropertySheet +from Products.ERP5Type.Base import getClassPropertyList from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.Utils import deprecated, createExpressionContext from Products.ERP5Type.XMLObject import XMLObject @@ -376,14 +377,24 @@ class ERP5TypeInformation(XMLObject, return default security.declarePublic('constructInstance') - def constructInstance( self, container, id, - created_by_builder=0, *args, **kw ): - """ - Build a "bare" instance of the appropriate type in - 'container', using 'id' as its id. - Call the init_script for the portal_type. - Returns the object. - """ + def constructInstance(self, container, id, created_by_builder=0, + temp_object=0, *args, **kw ): + """ + Build a "bare" instance of the appropriate type in + 'container', using 'id' as its id. + Call the init_script for the portal_type. + 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 # In case of temp object, we don't want to check security if (not (hasattr(container, 'isTempObject') @@ -418,7 +429,12 @@ class ERP5TypeInformation(XMLObject, kw['created_by_builder'] = created_by_builder 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') def updatePropertySheetDefinitionDict(self, definition_dict): @@ -451,61 +467,27 @@ class ERP5TypeInformation(XMLObject, 'getInstanceBaseCategoryList') def getInstanceBaseCategoryList(self): """ Return all base categories of the portal type """ - # try to get categories from a temporary object if possible - 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', ()))) + return list(self._getPropertyHolder()._categories) security.declareProtected(Permissions.AccessContentsInformation, 'getInstancePropertyAndBaseCategoryList') def getInstancePropertyAndBaseCategoryList(self): """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 - ps_list = [getattr(PropertySheet, p, None) - for p in self.getTypePropertySheetList()] - 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) - # 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 = set() + 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']) + for category in ob.getBaseCategoryList(): return_set.add(category) return_set.add(category + '_free_text') @@ -517,22 +499,8 @@ class ERP5TypeInformation(XMLObject, def getInstancePropertyMap(self): """ 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 - # 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() + return self.constructInstance(self, '', temp_object=1).propertyMap() def _edit(self, *args, **kw): """ diff --git a/product/ERP5Type/TranslationProviderBase.py b/product/ERP5Type/TranslationProviderBase.py index 9c4daf11be444b4415b8fa29a0f063f6dd4d1c18..7a59e5b2f1ca605d34e5dbedd35dfd577388d00e 100644 --- a/product/ERP5Type/TranslationProviderBase.py +++ b/product/ERP5Type/TranslationProviderBase.py @@ -58,34 +58,18 @@ class TranslationProviderBase(object): """ property_domain_dict = {} - # get the property sheet list for the portal type - ps_list = [getattr(PropertySheet, p, None) - for p in self.getTypePropertySheetList()] - 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) - # 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) + for prop in self._getPropertyHolder()._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), '_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 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 property_domain_dict.update(original_property_domain_dict) # And store