Commit 08a60a2d authored by Arnaud Fontaine's avatar Arnaud Fontaine

ExpressionMixin: Allow to specify the property storing the TALES Expression.

Until now it was only used in ERP5Catalog where the expression property is
`expression` for both Python Script and SQL Method but this is a common pattern
and will also needed for ERP5Workflow.
parent e8b41f91
Pipeline #13345 failed with stage
......@@ -64,7 +64,7 @@ class PythonScriptThroughZMI(XMLObject):
def __init__(self, *args, **kw):
assert False
class PythonScript(XMLObject, ZopePythonScript, ExpressionMixin):
class PythonScript(XMLObject, ZopePythonScript, ExpressionMixin('expression')):
""" Script python for ERP5
"""
......
......@@ -60,7 +60,7 @@ def manage_addSQLMethod(self, id, title='',
REQUEST['RESPONSE'].redirect( 'manage_main' )
return c
class SQLMethod(XMLObject, ZSQL, ExpressionMixin):
class SQLMethod(XMLObject, ZSQL, ExpressionMixin('expression')):
"""SQLMethod for ERP5.
"""
......
......@@ -29,30 +29,62 @@ from AccessControl import ClassSecurityInfo
from Products.CMFCore.Expression import Expression
from Products.ERP5Type import Permissions
from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5Type.Utils import convertToUpperCase
class ExpressionMixin:
security = ClassSecurityInfo()
def ExpressionMixin(property_reference='expression'):
"""
Mixin for a common pattern where ERP5 objects stores a TALES Expression as text.
def _setExpression(self, value):
Usage examples:
Python Script/SQL Method: expression_property (reference=expression)
GuardableMixin: guard_expression_property (reference=guard_expression)
CMFCore.Expression already stores the Expression text as 'text' property and
create a volatile for the instance, so this may seem redundant and we may
have stored an Expression instance directly on the object. However this
would make exported objects depend on CMFCore.Expression and not storing
"directly" user input.
"""
property_reference_uppercase = convertToUpperCase(property_reference)
volatile_attribute_name = '_v_' + property_reference + '_instance'
def _setter(self, value):
"""
_set<PropertyReference>()
"""
try:
del self._v_expression_instance
delattr(self, volatile_attribute_name)
except AttributeError:
pass
self._baseSetExpression(value)
getattr(self, '_baseSet' + property_reference_uppercase)(value)
security.declareProtected(Permissions.AccessContentsInformation, 'getExpressionInstance')
def getExpressionInstance(self, default=None):
def getter(self, default=None):
"""
get<PropertyReference>Instance()
"""
try:
return self._v_expression_instance
return getattr(self, volatile_attribute_name)
except AttributeError:
expression = self.getExpression()
expression = getattr(self, 'get' + property_reference_uppercase)()
# Check if the expression is not None, because Expression(<expression>)
# raises an error in case `expression` is empty or None.
if expression:
result = Expression(expression)
else:
result = None
self._v_expression_instance = result
setattr(self, volatile_attribute_name, result)
return result
InitializeClass(ExpressionMixin)
class ExpressionMixin:
security = ClassSecurityInfo()
_setter.__name__ = '_set' + property_reference_uppercase
setattr(ExpressionMixin, _setter.__name__, _setter)
getter.__name__ = 'get' + property_reference_uppercase + 'Instance'
setattr(ExpressionMixin, getter.__name__, getter)
ExpressionMixin.security.declareProtected(Permissions.AccessContentsInformation,
getter.__name__)
InitializeClass(ExpressionMixin)
return ExpressionMixin
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