Commit 609fd8c5 authored by Yoshinori Okuji's avatar Yoshinori Okuji

Add support for tales.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@1873 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 681a65e9
...@@ -50,7 +50,8 @@ class DefaultGetter(Method): ...@@ -50,7 +50,8 @@ class DefaultGetter(Method):
acquisition_sync_value, acquisition_sync_value,
storage_id=None, storage_id=None,
alt_accessor_id = None, alt_accessor_id = None,
is_list_type = 0 is_list_type = 0,
is_tales_type = 0
): ):
self._id = id self._id = id
self.__name__ = id self.__name__ = id
...@@ -69,12 +70,21 @@ class DefaultGetter(Method): ...@@ -69,12 +70,21 @@ class DefaultGetter(Method):
self._storage_id = storage_id self._storage_id = storage_id
self._alt_accessor_id = alt_accessor_id self._alt_accessor_id = alt_accessor_id
self._is_list_type = is_list_type self._is_list_type = is_list_type
self._is_tales_type = is_tales_type
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
if len(args) > 0: if len(args) > 0:
default = args[0] default = args[0]
else: else:
default = self._default default = self._default
# If this is a TALES expression and the option 'evaluate' is false,
# deal with the value as a simple object.
if self._is_tales_type and not kw.get('evaluate', 1):
is_list_type = 0
is_tales_type = 0
else:
is_list_type = self._is_list_type
is_tales_type = self._is_tales_type
return instance._getDefaultAcquiredProperty(self._key, default, self._null, return instance._getDefaultAcquiredProperty(self._key, default, self._null,
base_category=self._acquisition_base_category, base_category=self._acquisition_base_category,
portal_type=self._acquisition_portal_type, portal_type=self._acquisition_portal_type,
...@@ -84,7 +94,8 @@ class DefaultGetter(Method): ...@@ -84,7 +94,8 @@ class DefaultGetter(Method):
sync_value=self._acquisition_sync_value, sync_value=self._acquisition_sync_value,
storage_id=self._storage_id, storage_id=self._storage_id,
alt_accessor_id=self._alt_accessor_id, alt_accessor_id=self._alt_accessor_id,
is_list_type=self._is_list_type is_list_type=is_list_type,
is_tales_type=is_tales_type
) )
Getter = DefaultGetter Getter = DefaultGetter
...@@ -111,7 +122,8 @@ class ListGetter(Method): ...@@ -111,7 +122,8 @@ class ListGetter(Method):
acquisition_sync_value, acquisition_sync_value,
storage_id=None, storage_id=None,
alt_accessor_id = None, alt_accessor_id = None,
is_list_type = 0 is_list_type = 0,
is_tales_type = 0
): ):
self._id = id self._id = id
self.__name__ = id self.__name__ = id
...@@ -130,12 +142,21 @@ class ListGetter(Method): ...@@ -130,12 +142,21 @@ class ListGetter(Method):
self._storage_id = storage_id self._storage_id = storage_id
self._alt_accessor_id = alt_accessor_id self._alt_accessor_id = alt_accessor_id
self._is_list_type = is_list_type self._is_list_type = is_list_type
self._is_tales_type = is_tales_type
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
if len(args) > 0: if len(args) > 0:
default = args[0] default = args[0]
else: else:
default = self._default default = self._default
# If this is a TALES expression and the option 'evaluate' is false,
# deal with the value as a simple object.
if self._is_tales_type and not kw.get('evaluate', 1):
is_list_type = 0
is_tales_type = 0
else:
is_list_type = self._is_list_type
is_tales_type = self._is_tales_type
return instance._getAcquiredPropertyList(self._key, default, self._null, return instance._getAcquiredPropertyList(self._key, default, self._null,
base_category=self._acquisition_base_category, base_category=self._acquisition_base_category,
portal_type=self._acquisition_portal_type, portal_type=self._acquisition_portal_type,
...@@ -145,6 +166,8 @@ class ListGetter(Method): ...@@ -145,6 +166,8 @@ class ListGetter(Method):
sync_value=self._acquisition_sync_value, sync_value=self._acquisition_sync_value,
storage_id=self._storage_id, storage_id=self._storage_id,
alt_accessor_id=self._alt_accessor_id, alt_accessor_id=self._alt_accessor_id,
is_list_type=self._is_list_type) is_list_type=is_list_type,
is_tales_type=is_tales_type
)
SetGetter = ListGetter # ERROR SetGetter = ListGetter # ERROR
...@@ -50,7 +50,8 @@ class Getter(Method): ...@@ -50,7 +50,8 @@ class Getter(Method):
acquisition_sync_value, acquisition_sync_value,
storage_id=None, storage_id=None,
alt_accessor_id = None, alt_accessor_id = None,
is_list_type = 0, is_list_type = 0,
is_tales_type = 0
): ):
if type(portal_type) == type('a'): portal_type = (portal_type, ) if type(portal_type) == type('a'): portal_type = (portal_type, )
self._id = id self._id = id
...@@ -71,6 +72,7 @@ class Getter(Method): ...@@ -71,6 +72,7 @@ class Getter(Method):
self._storage_id = storage_id self._storage_id = storage_id
self._alt_accessor_id = alt_accessor_id self._alt_accessor_id = alt_accessor_id
self._is_list_type = is_list_type self._is_list_type = is_list_type
self._is_tales_type = is_tales_type
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
if len(args) > 0: if len(args) > 0:
...@@ -86,10 +88,11 @@ class Getter(Method): ...@@ -86,10 +88,11 @@ class Getter(Method):
sync_value=self._acquisition_sync_value, sync_value=self._acquisition_sync_value,
storage_id=self._storage_id, storage_id=self._storage_id,
alt_accessor_id=self._alt_accessor_id, alt_accessor_id=self._alt_accessor_id,
is_list_type=self._is_list_type is_list_type=self._is_list_type,
is_tales_type=self._is_tales_type,
) )
if value is not None: if value is not None:
return value.getProperty(self._acquired_property, default) return value.getProperty(self._acquired_property, default, **kw)
else: else:
return default return default
...@@ -115,8 +118,9 @@ class Setter(Method): ...@@ -115,8 +118,9 @@ class Setter(Method):
acquisition_sync_value, acquisition_sync_value,
storage_id=None, storage_id=None,
alt_accessor_id = None, alt_accessor_id = None,
is_list_type = 0, is_list_type = 0,
reindex = 0 is_tales_type = 0,
reindex = 0
): ):
if type(portal_type) == type('a'): portal_type = (portal_type, ) if type(portal_type) == type('a'): portal_type = (portal_type, )
self._id = id self._id = id
...@@ -137,9 +141,10 @@ class Setter(Method): ...@@ -137,9 +141,10 @@ class Setter(Method):
self._storage_id = storage_id self._storage_id = storage_id
self._alt_accessor_id = alt_accessor_id self._alt_accessor_id = alt_accessor_id
self._is_list_type = is_list_type self._is_list_type = is_list_type
self._is_tales_type = is_tales_type
self._reindex = reindex self._reindex = reindex
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
o = instance._getDefaultAcquiredProperty(self._key, None, self._null, o = instance._getDefaultAcquiredProperty(self._key, None, self._null,
base_category=self._acquisition_base_category, base_category=self._acquisition_base_category,
portal_type=self._acquisition_portal_type, portal_type=self._acquisition_portal_type,
...@@ -149,10 +154,11 @@ class Setter(Method): ...@@ -149,10 +154,11 @@ class Setter(Method):
sync_value=self._acquisition_sync_value, sync_value=self._acquisition_sync_value,
storage_id=self._storage_id, storage_id=self._storage_id,
alt_accessor_id=self._alt_accessor_id, alt_accessor_id=self._alt_accessor_id,
is_list_type=self._is_list_type is_list_type=self._is_list_type,
is_tales_type=self._is_tales_type
) )
if o is None: if o is None:
from Products.ERP5Type.Utils import assertAttributePortalType from Products.ERP5Type.Utils import assertAttributePortalType
assertAttributePortalType(instance, self._storage_id, self._portal_type) assertAttributePortalType(instance, self._storage_id, self._portal_type)
o = instance.newContent(id = self._storage_id, portal_type = self._portal_type[0]) o = instance.newContent(id = self._storage_id, portal_type = self._portal_type[0])
if self._reindex: if self._reindex:
......
...@@ -31,6 +31,8 @@ from TypeDefinition import type_definition, list_types, ATTRIBUTE_PREFIX ...@@ -31,6 +31,8 @@ from TypeDefinition import type_definition, list_types, ATTRIBUTE_PREFIX
from Accessor import Accessor as Method from Accessor import Accessor as Method
#from MethodObject import Method #from MethodObject import Method
from Products.ERP5Type.Cache import CachingMethod
# Creation of default constructor # Creation of default constructor
class func_code: pass class func_code: pass
...@@ -91,6 +93,13 @@ class Setter(Method): ...@@ -91,6 +93,13 @@ class Setter(Method):
method(*args, **kw) method(*args, **kw)
if self._reindex: instance.reindexObject() if self._reindex: instance.reindexObject()
def _evaluate_tales(instance=None, value=None):
expression = Expression(value)
econtext = createExpressionContext(instance)
return expression(econtext)
evaluate_tales = CachingMethod(_evaluate_tales, id = 'evaluate_tales', cache_duration=300)
class Getter(Method): class Getter(Method):
""" """
Gets an attribute value. A default value can be Gets an attribute value. A default value can be
...@@ -115,21 +124,20 @@ class Getter(Method): ...@@ -115,21 +124,20 @@ class Getter(Method):
if storage_id is None: if storage_id is None:
storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key) storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key)
self._storage_id = storage_id self._storage_id = storage_id
self._is_tales_type = (property_type == 'tales')
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
# We return the
if len(args) > 0: if len(args) > 0:
# We should not use here self._null but None instead XXX default = args[0]
if getattr(instance, self._storage_id, None) not in self._null:
return getattr(instance, self._storage_id)
else:
return args[0]
else: else:
# We should not use here self._null but None instead XXX default = self._default
if getattr(instance, self._storage_id, None) not in self._null: value = getattr(instance, self._storage_id, None)
return getattr(instance, self._storage_id) if value is not None:
if self._is_tales_type and kw.get('evaluate', 1):
return evaluate_tales(instance, value)
else: else:
return self._default return value
return default
class Tester(Method): class Tester(Method):
""" """
......
...@@ -30,6 +30,12 @@ from Base import func_code, type_definition, list_types, ATTRIBUTE_PREFIX, Metho ...@@ -30,6 +30,12 @@ from Base import func_code, type_definition, list_types, ATTRIBUTE_PREFIX, Metho
from TypeDefinition import asList, identity from TypeDefinition import asList, identity
import Base import Base
from Products.CMFCore.Expression import Expression
from Products.ERP5Type.Utils import createExpressionContext
from Products.ERP5Type.Cache import CachingMethod
from zLOG import LOG
class DefaultSetter(Method): class DefaultSetter(Method):
""" """
Sets the default attribute in a list Sets the default attribute in a list
...@@ -55,18 +61,23 @@ class DefaultSetter(Method): ...@@ -55,18 +61,23 @@ class DefaultSetter(Method):
self._item_cast = identity self._item_cast = identity
else: # Multivalued else: # Multivalued
self._cast = asList self._cast = asList
self._item_cast = type_definition[property_type]['cast'] self._item_cast = type_definition[property_type]['cast']
self._null = type_definition[property_type]['null'] self._null = type_definition[property_type]['null']
if storage_id is None: if storage_id is None:
storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key) storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key)
self._storage_id = storage_id self._storage_id = storage_id
self._is_tales_type = (property_type == 'tales')
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
# Turn the value into a list # Turn the value into a list
value = args[0] value = args[0]
if not self._reindex: if not self._reindex:
# Modify the property # Modify the property
if value in self._null: if self._is_tales_type:
if value in self._null:
value = None
setattr(instance, self._storage_id, value)
elif value in self._null:
# The value has no default property -> it is empty # The value has no default property -> it is empty
setattr(instance, self._storage_id, ()) setattr(instance, self._storage_id, ())
else: else:
...@@ -95,13 +106,15 @@ class DefaultSetter(Method): ...@@ -95,13 +106,15 @@ class DefaultSetter(Method):
if self._reindex: instance.reindexObject() if self._reindex: instance.reindexObject()
class Setter(DefaultSetter): class Setter(DefaultSetter):
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
value = args[0] value = args[0]
if not self._reindex: if not self._reindex:
# Modify the property # Modify the property
if value in self._null: if value in self._null:
setattr(instance, self._storage_id, None) setattr(instance, self._storage_id, None)
elif self._is_tales_type:
setattr(instance, self._storage_id, str(value))
else: else:
value = self._cast(args[0]) value = self._cast(args[0])
if self._item_cast is not identity: if self._item_cast is not identity:
...@@ -141,18 +154,23 @@ class SetSetter(Method): ...@@ -141,18 +154,23 @@ class SetSetter(Method):
self._item_cast = identity self._item_cast = identity
else: # Multivalued else: # Multivalued
self._cast = asList self._cast = asList
self._item_cast = type_definition[property_type]['cast'] self._item_cast = type_definition[property_type]['cast']
self._null = type_definition[property_type]['null'] self._null = type_definition[property_type]['null']
if storage_id is None: if storage_id is None:
storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key) storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key)
self._storage_id = storage_id self._storage_id = storage_id
self._is_tales_type = (property_type == 'tales')
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
# Turn the value into a list # Turn the value into a list
value = args[0] value = args[0]
if not self._reindex: if not self._reindex:
# Modify the property # Modify the property
if value in self._null: if self._is_tales_type:
if value in self._null:
value = None
setattr(instance, self._storage_id, value)
elif value in self._null:
# The value has no default property -> it is empty # The value has no default property -> it is empty
setattr(instance, self._storage_id, ()) setattr(instance, self._storage_id, ())
else: else:
...@@ -186,6 +204,14 @@ class SetSetter(Method): ...@@ -186,6 +204,14 @@ class SetSetter(Method):
method(*args, **kw) method(*args, **kw)
if self._reindex: instance.reindexObject() if self._reindex: instance.reindexObject()
def _evaluate_tales(instance=None, value=None):
expression = Expression(value)
econtext = createExpressionContext(instance)
return expression(econtext)
evaluate_tales = CachingMethod(_evaluate_tales, id = 'evaluate_tales', cache_duration=300)
class DefaultGetter(Method): class DefaultGetter(Method):
""" """
Gets the first item of a list Gets the first item of a list
...@@ -209,13 +235,23 @@ class DefaultGetter(Method): ...@@ -209,13 +235,23 @@ class DefaultGetter(Method):
if storage_id is None: if storage_id is None:
storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key) storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key)
self._storage_id = storage_id self._storage_id = storage_id
self._is_tales_type = (property_type == 'tales')
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
if len(args) > 0:
default = args[0]
else:
default = self._default
list_value = getattr(instance, self._storage_id, None) list_value = getattr(instance, self._storage_id, None)
if list_value is not None: if list_value is not None:
if self._is_tales_type:
if kw.get('evaluate', 1):
list_value = evaluate_tales(instance=instance, value=list_value)
else:
return list_value
if len(list_value) > 0: if len(list_value) > 0:
return list_value[0] return list_value[0]
return self._default return default
Getter = DefaultGetter Getter = DefaultGetter
...@@ -243,21 +279,23 @@ class ListGetter(Method): ...@@ -243,21 +279,23 @@ class ListGetter(Method):
if storage_id is None: if storage_id is None:
storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key) storage_id = "%s%s" % (ATTRIBUTE_PREFIX, key)
self._storage_id = storage_id self._storage_id = storage_id
self._is_tales_type = (property_type == 'tales')
def __call__(self, instance, *args, **kw): def __call__(self, instance, *args, **kw):
# We return the
if len(args) > 0: if len(args) > 0:
# We should not use here self._null but None instead XXX default = args[0]
if getattr(instance, self._storage_id, None) not in self._null:
return list(getattr(instance, self._storage_id))
else:
return args[0]
else: else:
# We should not use here self._null but None instead XXX default = self._default
if getattr(instance, self._storage_id, None) not in self._null: list_value = getattr(instance, self._storage_id, None)
return list(getattr(instance, self._storage_id)) # We should not use here self._null but None instead XXX
else: if list_value not in self._null:
return self._default if self._is_tales_type:
if kw.get('evaluate', 1):
list_value = evaluate_tales(instance=instance, value=list_value)
else:
return list_value
return list(list_value)
return default
SetGetter = ListGetter SetGetter = ListGetter
......
...@@ -152,6 +152,11 @@ type_definition = { ...@@ -152,6 +152,11 @@ type_definition = {
'default' : None, 'default' : None,
'isList' : 0, 'isList' : 0,
}, },
'tales' : { 'cast' : identity,
'null' : ('', 'None', None,),
'default' : None,
'isList' : 0,
},
} }
list_types = ('lines', 'tokens', 'selection', 'multiple selection') list_types = ('lines', 'tokens', 'selection', 'multiple selection')
......
...@@ -34,6 +34,7 @@ from Acquisition import aq_base, aq_inner, aq_acquire, aq_chain ...@@ -34,6 +34,7 @@ from Acquisition import aq_base, aq_inner, aq_acquire, aq_chain
from Products.CMFCore.WorkflowCore import WorkflowMethod from Products.CMFCore.WorkflowCore import WorkflowMethod
from Products.CMFCore.PortalContent import PortalContent from Products.CMFCore.PortalContent import PortalContent
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
from Products.CMFCore.Expression import Expression
from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
...@@ -43,8 +44,10 @@ from Products.ERP5Type import PropertySheet ...@@ -43,8 +44,10 @@ from Products.ERP5Type import PropertySheet
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Type.Utils import UpperCase from Products.ERP5Type.Utils import UpperCase
from Products.ERP5Type.Utils import convertToUpperCase, convertToMixedCase from Products.ERP5Type.Utils import convertToUpperCase, convertToMixedCase
from Products.ERP5Type.Utils import createExpressionContext
from Products.ERP5Type.Utils2 import _getListFor from Products.ERP5Type.Utils2 import _getListFor
from Products.ERP5Type.Accessor.TypeDefinition import list_types from Products.ERP5Type.Accessor.TypeDefinition import list_types
from Products.ERP5Type.Accessor import Base as BaseAccessor
from Products.ERP5Type.XMLExportImport import Base_asXML from Products.ERP5Type.XMLExportImport import Base_asXML
from Accessor import WorkflowState from Accessor import WorkflowState
...@@ -216,6 +219,14 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -216,6 +219,14 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
self.uid = uid # Else it will be generated when we need it self.uid = uid # Else it will be generated when we need it
self.sid = sid self.sid = sid
# XXX This is necessary to override getId which is also defined in SimpleItem.
security.declareProtected( Permissions.AccessContentsInformation, 'getId' )
for prop in PropertySheet.Base._properties:
if prop['id'] == 'id':
getId = BaseAccessor.Getter('getId', 'id', prop['type'],
default_value = prop.get('default'), storage_id = prop.get('storage_id'))
break
# Debug # Debug
def getOid(self): def getOid(self):
""" """
...@@ -235,7 +246,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -235,7 +246,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
def _getDefaultAcquiredProperty(self, key, default_value, null_value, def _getDefaultAcquiredProperty(self, key, default_value, null_value,
base_category=None, portal_type=None, copy_value=0, mask_value=0, sync_value=0, base_category=None, portal_type=None, copy_value=0, mask_value=0, sync_value=0,
accessor_id=None, depends=None, storage_id=None, alt_accessor_id=None, accessor_id=None, depends=None, storage_id=None, alt_accessor_id=None,
is_list_type=0): is_list_type=0, is_tales_type=0):
""" """
This method implements programmable acquisition of values in ERP5. This method implements programmable acquisition of values in ERP5.
...@@ -296,7 +307,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -296,7 +307,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
if not hasattr(TRANSACTION, '_erp5_acquisition_stack'): TRANSACTION._erp5_acquisition_stack = {} if not hasattr(TRANSACTION, '_erp5_acquisition_stack'): TRANSACTION._erp5_acquisition_stack = {}
acquisition_key = ('_getDefaultAcquiredProperty', self.getPath(), key, base_category, acquisition_key = ('_getDefaultAcquiredProperty', self.getPath(), key, base_category,
portal_type, copy_value, mask_value, sync_value, portal_type, copy_value, mask_value, sync_value,
accessor_id, depends, storage_id, alt_accessor_id, is_list_type) accessor_id, depends, storage_id, alt_accessor_id, is_list_type, is_tales_type)
if TRANSACTION._erp5_acquisition_stack.has_key(acquisition_key): return null_value if TRANSACTION._erp5_acquisition_stack.has_key(acquisition_key): return null_value
TRANSACTION._erp5_acquisition_stack[acquisition_key] = 1 TRANSACTION._erp5_acquisition_stack[acquisition_key] = 1
...@@ -304,11 +315,16 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -304,11 +315,16 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
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): value = getattr(self, storage_id, None)
if getattr(self, storage_id) != None: if mask_value and value is not None:
# Pop context # Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key] del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return getattr(self, storage_id) if is_tales_type:
expression = Expression(value)
econtext = createExpressionContext(self)
return expression(econtext)
else:
return value
# 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))
...@@ -408,34 +424,26 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -408,34 +424,26 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
if not hasattr(TRANSACTION, '_erp5_acquisition_stack'): TRANSACTION._erp5_acquisition_stack = {} if not hasattr(TRANSACTION, '_erp5_acquisition_stack'): TRANSACTION._erp5_acquisition_stack = {}
acquisition_key = ('_getAcquiredPropertyList', self.getPath(), key, base_category, acquisition_key = ('_getAcquiredPropertyList', self.getPath(), key, base_category,
portal_type, copy_value, mask_value, sync_value, portal_type, copy_value, mask_value, sync_value,
accessor_id, depends, storage_id, alt_accessor_id, is_list_type) accessor_id, depends, storage_id, alt_accessor_id, is_list_type, is_tales_type)
if TRANSACTION._erp5_acquisition_stack.has_key(acquisition_key): return null_value if TRANSACTION._erp5_acquisition_stack.has_key(acquisition_key): return null_value
TRANSACTION._erp5_acquisition_stack[acquisition_key] = 1 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): value = getattr(self, storage_id, None)
if getattr(self, storage_id) != None: if mask_value and value is not None:
# Pop context # Pop context
del TRANSACTION._erp5_acquisition_stack[acquisition_key] del TRANSACTION._erp5_acquisition_stack[acquisition_key]
return getattr(self, storage_id) if is_tales_type:
if type(base_category) == 'a': expression = Expression(value)
base_category = (base_category, ) econtext = createExpressionContext(self)
if type(portal_type) == 'a': return expression(econtext)
portal_type = (portal_type, ) else:
super = None return value
psuper = [] super_list = self._getAcquiredValueList(base_category, portal_type=portal_type) # Full acquisition
for cat in base_category: super_list = filter(lambda o: o.getPhysicalPath() != self.getPhysicalPath(), super_list) # Make sure we do not create stupid loop here
#super_list = self._getValueList(cat) # We only do a single jump - no acquisition if len(super_list) > 0:
super_list = self._getAcquiredValueList(cat) # Full acquisition
for super in super_list:
if super is not None:
# Performance should be increased
for ptype in portal_type:
if ptype == super.portal_type:
psuper.append(super)
if len(psuper) > 0:
value = [] value = []
for super in psuper: for super in super_list:
if accessor_id is None: if accessor_id is None:
if is_list_type: if is_list_type:
result = super.getPropertyList(key) result = super.getPropertyList(key)
...@@ -473,7 +481,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -473,7 +481,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
return default_value return default_value
security.declareProtected( Permissions.AccessContentsInformation, 'getProperty' ) security.declareProtected( Permissions.AccessContentsInformation, 'getProperty' )
def getProperty(self, key, d=None): def getProperty(self, key, d=None, **kw):
""" """
Previous Name: getValue Previous Name: getValue
...@@ -483,13 +491,13 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -483,13 +491,13 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
aq_self = aq_base(self) aq_self = aq_base(self)
if hasattr(aq_self, accessor_name): if hasattr(aq_self, accessor_name):
method = getattr(self, accessor_name) method = getattr(self, accessor_name)
return method() return method(**kw)
elif hasattr(aq_self, key): #elif hasattr(aq_self, key):
value = getattr(aq_self, key) # value = getattr(aq_self, key)
if callable(value): value = value() # if callable(value): value = value()
return value # return value
else: else:
return ERP5PropertyManager.getProperty(self, key, d=d) return ERP5PropertyManager.getProperty(self, key, d=d, **kw)
security.declareProtected( Permissions.AccessContentsInformation, 'getPropertyList' ) security.declareProtected( Permissions.AccessContentsInformation, 'getPropertyList' )
def getPropertyList(self, key, d=None): def getPropertyList(self, key, d=None):
...@@ -524,6 +532,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -524,6 +532,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
**kw allows to call setProperty as a generic setter (ex. setProperty(value_uid, portal_type=)) **kw allows to call setProperty as a generic setter (ex. setProperty(value_uid, portal_type=))
""" """
LOG('_setProperty', 0, 'key = %r, value = %r, type = %r, kw = %r' % (key, value, type, kw))
#LOG('In _setProperty',0, str(key)) #LOG('In _setProperty',0, str(key))
if type is not 'string': # Speed if type is not 'string': # Speed
if type in list_types: # Patch for OFS PropertyManager if type in list_types: # Patch for OFS PropertyManager
...@@ -534,7 +543,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -534,7 +543,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
# since we will change the value on self # since we will change the value on self
# rather than through implicit aquisition # rather than through implicit aquisition
if hasattr(aq_self, accessor_name): if hasattr(aq_self, accessor_name):
#LOG("Calling: ",0, '%s %s ' % (accessor_name, kw[key])) #LOG("Calling: ",0, '%r %r ' % (accessor_name, key))
method = getattr(self, accessor_name) method = getattr(self, accessor_name)
return method(value, **kw) return method(value, **kw)
"""# Make sure we change the default value again """# Make sure we change the default value again
...@@ -547,7 +556,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -547,7 +556,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
method(kw[new_key])""" method(kw[new_key])"""
public_accessor_name = 'set' + UpperCase(key) public_accessor_name = 'set' + UpperCase(key)
if hasattr(aq_self, public_accessor_name): if hasattr(aq_self, public_accessor_name):
#LOG("Calling: ",0, '%s %s ' % (public_accessor_name, kw[key])) #LOG("Calling: ",0, '%r %r ' % (public_accessor_name, key))
method = getattr(self, public_accessor_name) method = getattr(self, public_accessor_name)
method(value, **kw) method(value, **kw)
else: else:
......
...@@ -1018,7 +1018,8 @@ def createDefaultAccessors(klass, id, prop = None): ...@@ -1018,7 +1018,8 @@ def createDefaultAccessors(klass, id, prop = None):
prop.get('acquisition_sync_value',0), prop.get('acquisition_sync_value',0),
storage_id = prop.get('storage_id'), storage_id = prop.get('storage_id'),
alt_accessor_id = prop.get('alt_accessor_id'), alt_accessor_id = prop.get('alt_accessor_id'),
is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)) is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)),
is_tales_type = (prop['type'] == 'tales')
) )
# The default accessor returns the first item in a list # The default accessor returns the first item in a list
default_accessor = base_accessor default_accessor = base_accessor
...@@ -1036,7 +1037,8 @@ def createDefaultAccessors(klass, id, prop = None): ...@@ -1036,7 +1037,8 @@ def createDefaultAccessors(klass, id, prop = None):
prop.get('acquisition_sync_value',0), prop.get('acquisition_sync_value',0),
storage_id = prop.get('storage_id'), storage_id = prop.get('storage_id'),
alt_accessor_id = prop.get('alt_accessor_id'), alt_accessor_id = prop.get('alt_accessor_id'),
is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)) is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)),
is_tales_type = (prop['type'] == 'tales')
) )
# Base Getter # Base Getter
accessor_name = 'get' + UpperCase(id) accessor_name = 'get' + UpperCase(id)
...@@ -1108,7 +1110,8 @@ def createDefaultAccessors(klass, id, prop = None): ...@@ -1108,7 +1110,8 @@ def createDefaultAccessors(klass, id, prop = None):
prop.get('acquisition_sync_value',0), prop.get('acquisition_sync_value',0),
storage_id = prop.get('storage_id'), storage_id = prop.get('storage_id'),
alt_accessor_id = prop.get('alt_accessor_id'), alt_accessor_id = prop.get('alt_accessor_id'),
is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)) is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)),
is_tales_type = (prop['type'] == 'tales')
) )
if not hasattr(klass, accessor_name) or prop.get('override',0): if not hasattr(klass, accessor_name) or prop.get('override',0):
setattr(klass, accessor_name, base_accessor) setattr(klass, accessor_name, base_accessor)
...@@ -1135,6 +1138,7 @@ def createDefaultAccessors(klass, id, prop = None): ...@@ -1135,6 +1138,7 @@ def createDefaultAccessors(klass, id, prop = None):
storage_id = prop.get('storage_id'), storage_id = prop.get('storage_id'),
alt_accessor_id = prop.get('alt_accessor_id'), alt_accessor_id = prop.get('alt_accessor_id'),
is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)), is_list_type = (prop['type'] in list_types or prop.get('multivalued', 0)),
is_tales_type = (prop['type'] == 'tales'),
reindex = 1 reindex = 1
) )
if not hasattr(klass, accessor_name) or prop.get('override',0): if not hasattr(klass, accessor_name) or prop.get('override',0):
...@@ -1642,7 +1646,7 @@ def createDefaultAccessors(klass, id, prop = None): ...@@ -1642,7 +1646,7 @@ def createDefaultAccessors(klass, id, prop = None):
tester_name = '_baseHas' + UpperCase(id) tester_name = '_baseHas' + UpperCase(id)
if not hasattr(BaseClass, tester_name): if not hasattr(BaseClass, tester_name):
setattr(BaseClass, tester_name, tester) setattr(BaseClass, tester_name, tester)
if prop['type'] == 'object': elif prop['type'] == 'object':
tester_name = 'has' + UpperCase(id) tester_name = 'has' + UpperCase(id)
tester = Object.Tester(tester_name, id, prop['type'], tester = Object.Tester(tester_name, id, prop['type'],
storage_id = prop.get('storage_id')) storage_id = prop.get('storage_id'))
......
...@@ -65,9 +65,15 @@ ObjectManager._importObjectFromFile=PatchedObjectManager._importObjectFromFile ...@@ -65,9 +65,15 @@ ObjectManager._importObjectFromFile=PatchedObjectManager._importObjectFromFile
# Properties # Properties
from OFS.PropertyManager import PropertyManager, type_converters from OFS.PropertyManager import PropertyManager, type_converters
from OFS.PropertyManager import escape from OFS.PropertyManager import escape
from Globals import DTMLFile
from Products.ERP5Type.Utils import createExpressionContext
from Products.CMFCore.Expression import Expression
class ERP5PropertyManager(PropertyManager): class ERP5PropertyManager(PropertyManager):
manage_propertiesForm=DTMLFile('dtml/properties', globals(),
property_extensible_schema__=1)
def _updateProperty(self, id, value): def _updateProperty(self, id, value):
# Update the value of an existing property. If value # Update the value of an existing property. If value
# is a string, an attempt will be made to convert # is a string, an attempt will be made to convert
...@@ -89,6 +95,19 @@ class ERP5PropertyManager(PropertyManager): ...@@ -89,6 +95,19 @@ class ERP5PropertyManager(PropertyManager):
return 1 return 1
return 0 return 0
def getProperty(self, id, d=None, evaluate=1):
"""Get the property 'id', returning the optional second
argument or None if no such property is found."""
type = self.getPropertyType(id)
if evaluate and type == 'tales':
value = getattr(self, id)
expression = Expression(value)
econtext = createExpressionContext(self)
return expression(econtext)
elif type:
return getattr(self, id)
return d
def getPropertyType(self, id): def getPropertyType(self, id):
"""Get the type of property 'id', returning None if no """Get the type of property 'id', returning None if no
such property exists""" such property exists"""
...@@ -167,6 +186,18 @@ class ERP5PropertyManager(PropertyManager): ...@@ -167,6 +186,18 @@ class ERP5PropertyManager(PropertyManager):
dict[p['id']]=p dict[p['id']]=p
return dict return dict
def manage_addProperty(self, id, value, type, REQUEST=None):
"""Add a new property via the web. Sets a new property with
the given id, type, and value."""
if type_converters.has_key(type):
value=type_converters[type](value)
LOG('manage_addProperty', 0, 'id = %r, value = %r, type = %r, REQUEST = %r' % (id, value, type, REQUEST))
self._setProperty(id.strip(), value, type)
if REQUEST is not None:
return self.manage_propertiesForm(self, REQUEST)
PropertyManager.manage_addProperty = ERP5PropertyManager.manage_addProperty
PropertyManager.manage_propertiesForm = ERP5PropertyManager.manage_propertiesForm
PropertyManager._updateProperty = ERP5PropertyManager._updateProperty PropertyManager._updateProperty = ERP5PropertyManager._updateProperty
PropertyManager.getPropertyType = ERP5PropertyManager.getPropertyType PropertyManager.getPropertyType = ERP5PropertyManager.getPropertyType
PropertyManager._setProperty = ERP5PropertyManager._setProperty PropertyManager._setProperty = ERP5PropertyManager._setProperty
...@@ -177,7 +208,11 @@ PropertyManager.propertyItems = ERP5PropertyManager.propertyItems ...@@ -177,7 +208,11 @@ PropertyManager.propertyItems = ERP5PropertyManager.propertyItems
PropertyManager._propertyMap = ERP5PropertyManager._propertyMap PropertyManager._propertyMap = ERP5PropertyManager._propertyMap
PropertyManager.propdict = ERP5PropertyManager.propdict PropertyManager.propdict = ERP5PropertyManager.propdict
PropertyManager.hasProperty = ERP5PropertyManager.hasProperty PropertyManager.hasProperty = ERP5PropertyManager.hasProperty
PropertyManager.getProperty = ERP5PropertyManager.getProperty
from ZPublisher.Converters import type_converters, field2string
type_converters['tales'] = field2string
############################################################################## ##############################################################################
# XML content of zsql methods # XML content of zsql methods
...@@ -823,7 +858,7 @@ class ERP5WorkflowTool(WorkflowTool): ...@@ -823,7 +858,7 @@ class ERP5WorkflowTool(WorkflowTool):
for w in wfs: for w in wfs:
w.notifyBefore(ob, method_id, args=args, kw=kw) w.notifyBefore(ob, method_id, args=args, kw=kw)
# Check if there is at least 1 non interaction workflow # Check if there is at least 1 non interaction workflow
if no_interaction: if no_interaction:
for w in wf_list: for w in wf_list:
if w.meta_type != 'Interaction Workflow': if w.meta_type != 'Interaction Workflow':
result = self._invokeWithNotification( result = self._invokeWithNotification(
......
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