Commit ad8b1ee3 authored by Jean-Paul Smets's avatar Jean-Paul Smets

Added loop detection system for getAcquiredProperty API (based on request)


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@1178 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 1fb47134
...@@ -188,20 +188,33 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -188,20 +188,33 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
Other case : we want to change the phone number of a related object without Other case : we want to change the phone number of a related object without
going to edit the related object going to edit the related object
""" """
# Push context to prevent loop
from Globals import get_request
TRANSACTION = get_transaction()
if not hasattr(TRANSACTION, '_erp5_acquisition_stack'): TRANSACTION._erp5_acquisition_stack = {}
acquisition_key = ('_getDefaultAcquiredProperty', self.getPath(), key, base_category,
portal_type, copy_value, mask_value, sync_value,
accessor_id, depends, storage_id, alt_accessor_id, is_list_type)
if TRANSACTION._erp5_acquisition_stack.has_key(acquisition_key): return null_value
TRANSACTION._erp5_acquisition_stack[acquisition_key] = 1
#LOG("Get Acquired Property key",0,str(key)) #LOG("Get Acquired Property key",0,str(key))
if storage_id is None: storage_id=key if storage_id is None: storage_id=key
# LOG("Get Acquired Property storage_id",0,str(storage_id)) # LOG("Get Acquired Property storage_id",0,str(storage_id))
# If we hold an attribute and mask_value is set, return the attribute # If we hold an attribute and mask_value is set, return the attribute
if mask_value and hasattr(self, storage_id): if mask_value and hasattr(self, storage_id):
if getattr(self, storage_id) != None: if getattr(self, storage_id) != None:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return getattr(self, storage_id) return getattr(self, storage_id)
# Retrieve the list of related objects # Retrieve the list of related objects
#LOG("Get Acquired Property self",0,str(self)) #LOG("Get Acquired Property self",0,str(self))
#LOG("Get Acquired Property portal_type",0,str(portal_type)) #LOG("Get Acquired Property portal_type",0,str(portal_type))
#LOG("Get Acquired Property base_category",0,str(base_category)) #LOG("Get Acquired Property base_category",0,str(base_category))
#super_list = self._getValueList(base_category, portal_type=portal_type) # We only do a single jump #super_list = self._getValueList(base_category, portal_type=portal_type) # We only do a single jump
super_list = self._getAcquiredValueList(base_category, portal_type=portal_type) # We only do a single jump super_list = self._getAcquiredValueList(base_category, portal_type=portal_type) # Full acquisition
super_list = filter(lambda o: o.getPhysicalPath() != self.getPhysicalPath(), super_list) # Make sure we do not create stupid loop here super_list = filter(lambda o: o.getPhysicalPath() != self.getPhysicalPath(), super_list) # Make sure we do not create stupid loop here
#LOG("Get Acquired Property super_list",0,str(super_list)) #LOG("Get Acquired Property super_list",0,str(super_list))
#LOG("Get Acquired Property accessor_id",0,str(accessor_id)) #LOG("Get Acquired Property accessor_id",0,str(accessor_id))
...@@ -237,6 +250,8 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -237,6 +250,8 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
else: else:
result = None result = None
if result is not None: if result is not None:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return result return result
else: else:
#LOG("alt_accessor_id",0,str(alt_accessor_id)) #LOG("alt_accessor_id",0,str(alt_accessor_id))
...@@ -251,16 +266,26 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -251,16 +266,26 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
if type(result) is type([]) or type(result) is type(()): if type(result) is type([]) or type(result) is type(()):
# We must provide the first element of the alternate result # We must provide the first element of the alternate result
if len(result) > 0: if len(result) > 0:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return result[0] return result[0]
else: else:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return result return result
else: else:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
# Result is a simple type # Result is a simple type
return result return result
if copy_value: if copy_value:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return getattr(self,storage_id, default_value) return getattr(self,storage_id, default_value)
else: else:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
# Return the default value defined at the class level XXXXXXXXXXXXXXX # Return the default value defined at the class level XXXXXXXXXXXXXXX
return default_value return default_value
...@@ -275,10 +300,23 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -275,10 +300,23 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
portal_type portal_type
copy_value copy_value
depends depends
""" """
# Push context to prevent loop
from Globals import get_request
TRANSACTION = get_transaction()
if not hasattr(TRANSACTION, '_erp5_acquisition_stack'): TRANSACTION._erp5_acquisition_stack = {}
acquisition_key = ('_getAcquiredPropertyList', self.getPath(), key, base_category,
portal_type, copy_value, mask_value, sync_value,
accessor_id, depends, storage_id, alt_accessor_id, is_list_type)
if TRANSACTION._erp5_acquisition_stack.has_key(acquisition_key): return null_value
TRANSACTION._erp5_acquisition_stack[acquisition_key] = 1
if storage_id is None: storage_id=key if storage_id is None: storage_id=key
if mask_value and hasattr(self, storage_id): if mask_value and hasattr(self, storage_id):
if getattr(self, storage_id) != None: if getattr(self, storage_id) != None:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return getattr(self, storage_id) return getattr(self, storage_id)
if type(base_category) == 'a': if type(base_category) == 'a':
base_category = (base_category, ) base_category = (base_category, )
...@@ -288,7 +326,7 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -288,7 +326,7 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
psuper = [] psuper = []
for cat in base_category: for cat in base_category:
#super_list = self._getValueList(cat) # We only do a single jump - no acquisition #super_list = self._getValueList(cat) # We only do a single jump - no acquisition
super_list = self._getAcquiredValueList(cat) # We only do a single jump - no acquisition super_list = self._getAcquiredValueList(cat) # Full acquisition
for super in super_list: for super in super_list:
if super is not None: if super is not None:
# Performance should be increased # Performance should be increased
...@@ -320,12 +358,18 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -320,12 +358,18 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
if copy_value: if copy_value:
if not hasattr(self, storage_id): if not hasattr(self, storage_id):
setattr(self, value) setattr(self, value)
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return value return value
else: else:
# ????? # ?????
if copy_value: if copy_value:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return getattr(self,storage_id, default_value) return getattr(self,storage_id, default_value)
else: else:
# Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return default_value return default_value
security.declareProtected( Permissions.AccessContentsInformation, 'getProperty' ) security.declareProtected( Permissions.AccessContentsInformation, 'getProperty' )
...@@ -460,6 +504,7 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -460,6 +504,7 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
except: except:
categoryIds = [] categoryIds = []
id_changed = 0 id_changed = 0
self._v_modified_property_dict = {}
for key in kw.keys(): for key in kw.keys():
#if key in categoryIds: #if key in categoryIds:
# self._setCategoryMembership(key, kw[key]) # self._setCategoryMembership(key, kw[key])
...@@ -472,12 +517,13 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -472,12 +517,13 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
elif hasattr(self, accessor_name): elif hasattr(self, accessor_name):
#LOG("Calling: ",0, accessor_name) #LOG("Calling: ",0, accessor_name)
method = getattr(self, accessor_name) method = getattr(self, accessor_name)
old_value = method() old_value = method() # XXX Why not use getProperty ???
#LOG("Old value: ",0, str(old_value)) #LOG("Old value: ",0, str(old_value))
#LOG("New value: ",0, str(kw[key])) #LOG("New value: ",0, str(kw[key]))
else: else:
old_value = None old_value = None
if old_value != kw[key] or force_update: if old_value != kw[key] or force_update:
self._v_modified_property_dict[key] = old_value # We keep in a thread var the previous values - this can be useful for interaction workflow to implement lookups
self._setProperty(key, kw[key]) self._setProperty(key, kw[key])
elif self.id != kw['id']: elif self.id != kw['id']:
self.recursiveFlushActivity(invoke=1) # Do not rename until everything flushed self.recursiveFlushActivity(invoke=1) # Do not rename until everything flushed
......
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