Commit 6846d20c authored by Julien Muchembled's avatar Julien Muchembled

* never create temp objects with CMF constructInstance

 * init scripts are never executed on temp objects
 * create constructor for Base and XMLObject temp objects
 * also filter content types for temp objects:
   * new parameter to Folder.newContent to bypass filtering
   * ERP5/Tool/Domain.py needs to bypass filtering
 * fix Delivery_updateAppliedRule to allow creation of portal type 'Internal Packing List' and 'Returned Sale Packing List'

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@21530 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent c63f2474
......@@ -108,7 +108,8 @@ class Domain(Predicate, MetaNode, MetaResource):
We need a way to know how deep we are in the domain generation
to prevent infinite recursion XXX not implemented
"""
klass = tmp_domain_generator = self.newContent(portal_type='Domain Generator', temp_object=1)
klass = tmp_domain_generator = self.newContent(
portal_type='Domain Generator', temp_object=1, filter_content_types=0)
script = self.getDomainGeneratorMethodId('')
return tmp_domain_generator.getDomainGeneratorList(depth=depth, klass=klass, script=script, parent=self)
......@@ -117,9 +118,9 @@ class Domain(Predicate, MetaNode, MetaResource):
"""
We generate temp domain here because we must set an aquisition wrapper
"""
domain = self.newContent(id=id, portal_type='Domain', temp_object=1)
domain = domain.__of__(self)
return domain
domain = self.newContent(id=id, portal_type='Domain',
temp_object=1, filter_content_types=0)
return domain.__of__(self)
def getChildDomainValueList(self, parent = None, **kw):
"""
......
......@@ -78,6 +78,9 @@ applied_rule_dict = {\n
\'Sale Order\': \'default_order_rule\',\n
\'Sale Packing List\': \'default_delivery_rule\',\n
\'Sale Invoice Transaction\': \'default_invoice_rule\',\n
\n
\'Internal Packing List\': None,\n
\'Returned Sale Packing List\': None,\n
\n
\'Accounting Rule Cell\': None,\n
\'Accounting Transaction\': None,\n
......
842
\ No newline at end of file
843
\ No newline at end of file
......@@ -410,38 +410,25 @@ class PropertyHolder:
"""
Return a list of tuple (id, method) for every accessor
"""
accessor_method_item_list = []
for x, y in self._getItemList():
if isinstance(y, types.TupleType):
if y is WORKFLOW_METHOD_MARKER or x == '__ac_permissions__':
continue
if len(y) == 0:
raise ValueError("problem at %s %s" % (self._portal_type, x))
result = []
#for x in self._getItemList():
#if isinstance(x[1], Accessor):
#result.append(x)
#elif isinstance(x[1], types.TupleType):
#LOG('isinstance', 0, str(x))
#if x[1] is not WORKFLOW_METHOD_MARKER and issubclass(x[1][0], Accessor):
#result.append(x)
#return result
return [x for x in self._getItemList() if isinstance(x[1], Accessor)
or (isinstance(x[1], types.TupleType)
and x[1] is not WORKFLOW_METHOD_MARKER
and x[0] != '__ac_permissions__'
and issubclass(x[1][0], Accessor))]
if not issubclass(y[0], Accessor):
continue
elif not isinstance(y, Accessor):
continue
accessor_method_item_list.append((x, y))
return accessor_method_item_list
def getAccessorMethodIdList(self):
"""
Return the list of accessor IDs
"""
for x, y in self._getItemList():
if isinstance(y, types.TupleType):
if len(y) == 0:
raise ValueError("problem at %s %s" % (self._portal_type, x))
return [x[0] for x in self._getItemList() if isinstance(x[1], Accessor)
or (isinstance(x[1], types.TupleType)
and x[1] is not WORKFLOW_METHOD_MARKER
and x[0] != '__ac_permissions__'
and issubclass(x[1][0], Accessor))]
return [ x[0] for x in self.getAccessorMethodItemList() ]
def getWorkflowMethodItemList(self):
"""
......
......@@ -100,11 +100,19 @@ class FolderMixIn(ExtensionClass.Base):
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
security.declarePublic('isTempObject')
def isTempObject(self):
"""Return true if self is an instance of a temporary document class.
"""
# Note: Folder inherits from Base and FolderMixIn but Base has priority.
return 0
security.declarePublic('newContent')
def newContent(self, id=None, portal_type=None, id_group=None,
default=None, method=None, immediate_reindex=0,
container=None, created_by_builder=0, activate_kw=None,
is_indexable=None, temp_object=0, reindex_kw=None, **kw):
is_indexable=None, temp_object=0, reindex_kw=None,
filter_content_types=1, **kw):
"""Creates a new content.
This method is public, since TypeInformation.constructInstance will perform
the security check.
......@@ -112,29 +120,41 @@ class FolderMixIn(ExtensionClass.Base):
pt = self._getTypesTool()
if container is None:
container = self
if id is None and not temp_object:
temp_container = container.isTempObject()
# The only case where the id is unused (because the new object is not added
# to its parent) is when a temp object is created inside a non-temp object.
if id is None and (temp_container or not temp_object):
new_id = str(container.generateNewId( id_group=id_group,
default=default,
method=method))
else:
new_id = str(id)
if portal_type is None:
# XXX This feature is very confusing
# And made the code more difficult to update
portal_type = container.allowedContentTypes()[0].id
elif filter_content_types:
type_info = pt.getTypeInfo(container)
if type_info is not None and not type_info.allowType(portal_type) and \
'portal_trash' not in container.getPhysicalPath():
raise ValueError('Disallowed subobject type: %s' % portal_type)
# we get an object from factory only for first temp container object
# otherwise we get an id so we can use the classic way
if temp_object and not getattr(container, 'isTempObject', lambda: 0)():
from Products.ERP5Type import Document
factory_name = 'newTemp%s' %(portal_type.replace(' ', ''))
m = getattr(Document, factory_name)
new_instance = m(container, new_id)
# 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:
myType = pt.getTypeInfo(container)
if myType is not None and not myType.allowType( portal_type ) and \
'portal_trash' not in container.getPhysicalPath():
raise ValueError('Disallowed subobject type: %s' % portal_type)
pt.constructContent( type_name=portal_type,
container=container,
id=new_id,
......
......@@ -249,27 +249,6 @@ class ERP5TypeInformationMixIn( FactoryTypeInformation,
return default
def _getFactoryMethod(self, container, check_security=1):
if not self.product or not self.factory:
raise ValueError, ('Product factory for %s was undefined' %
self.getId())
p = container.manage_addProduct[self.product]
if hasattr(container, 'isTempObject') and container.isTempObject():
factory_name = self.factory.replace('add', 'newTemp') # We suppose here
# that methods are names addClass or newTempClass
# Prefix should be moved to a central place.
m = getattr(p, factory_name, None)
else:
m = getattr(p, self.factory, None)
if m is None:
raise ValueError, ('Product factory for %s was invalid' %
self.getId())
if not check_security:
return m
if getSecurityManager().validate(p, p, self.factory, m):
return m
raise AccessControl_Unauthorized( 'Cannot create %s' % self.getId() )
security.declarePublic('constructInstance')
def constructInstance( self, container, id,
created_by_builder=0, *args, **kw ):
......
......@@ -367,17 +367,15 @@ class TempDocumentConstructor(DocumentConstructor):
self.klass = TempDocument
def __call__(self, folder, id, REQUEST=None, **kw):
# CMF constructInstance is never used to build temp objects
# so we never return the id.
o = self.klass(id)
if folder.isTempObject():
folder._setObject(id, o)
o = o.__of__(folder)
if kw:
o.__of__(folder)._edit(force_update=1, **kw)
isTempObject = getattr(folder, 'isTempObject', None)
if isTempObject is not None and isTempObject():
folder._setObject(id, o)# Temp Object in Temp Object should use containment
return id # return id to be compatible with CMF constructInstance
else: # Temp Object in Persistent Object should use acquisition
o = o.__of__(folder)
return o # We should return id if called on a Factory Dispatcher
# and return o if called on a container
o._edit(force_update=1, **kw)
return o
python_file_parser = re.compile('^(.*)\.py$')
......@@ -869,6 +867,9 @@ def initializeProduct( context,
if hasattr(content_class, 'add' + content_class.__name__):
extra_content_constructors += [
getattr(content_class, 'add' + content_class.__name__)]
if hasattr(content_class, 'newTemp' + content_class.__name__):
extra_content_constructors += [
getattr(content_class, 'newTemp' + content_class.__name__)]
# Define FactoryTypeInformations for all content classes
contentFactoryTypeInformations = []
......@@ -993,12 +994,19 @@ def setDefaultConstructor(klass):
"""
Create the default content creation method
"""
if not hasattr(klass, 'add' + klass.__name__):
document_constructor_name = 'add' + klass.__name__
if not hasattr(klass, document_constructor_name):
document_constructor = DocumentConstructor(klass)
document_constructor_name = "add%s" % klass.__name__
setattr(klass, document_constructor_name, document_constructor)
document_constructor.__name__ = document_constructor_name
temp_document_constructor_name = 'newTemp' + klass.__name__
if not hasattr(klass, temp_document_constructor_name):
temp_document_constructor = TempDocumentConstructor(klass)
setattr(klass, temp_document_constructor_name, temp_document_constructor)
temp_document_constructor.__name__ = temp_document_constructor_name
klass.security.declarePublic(temp_document_constructor_name)
def createExpressionContext(object, portal=None):
"""
......
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