Back to index

plone3  3.1.7
Expression.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 # 
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 # 
00012 ##############################################################################
00013 """ Expressions in a web-configurable workflow.
00014 
00015 $Id: Expression.py 74063 2007-04-09 21:23:43Z tseaver $
00016 """
00017 from warnings import warn
00018 
00019 import Globals
00020 from Globals import Persistent
00021 from Acquisition import aq_inner, aq_parent
00022 from AccessControl import getSecurityManager, ClassSecurityInfo
00023 from DateTime import DateTime
00024 
00025 from Products.CMFCore.WorkflowCore import ObjectDeleted, ObjectMoved
00026 from Products.CMFCore.Expression import Expression
00027 from Products.CMFCore.interfaces import ISiteRoot
00028 from Products.PageTemplates.Expressions import getEngine
00029 from Products.PageTemplates.Expressions import SecureModuleImporter
00030 
00031 
00032 # We don't import SafeMapping from Products.PageTemplates.TALES
00033 # because it's deprecated in Zope 2.10
00034 from MultiMapping import MultiMapping
00035 class SafeMapping(MultiMapping):
00036     """Mapping with security declarations and limited method exposure.
00037 
00038     Since it subclasses MultiMapping, this class can be used to wrap
00039     one or more mapping objects.  Restricted Python code will not be
00040     able to mutate the SafeMapping or the wrapped mappings, but will be
00041     able to read any value.
00042     """
00043     __allow_access_to_unprotected_subobjects__ = 1
00044     push = pop = None
00045     _push = MultiMapping.push
00046     _pop = MultiMapping.pop
00047 
00048 
00049 class StateChangeInfo:
00050     '''
00051     Provides information for expressions and scripts.
00052     '''
00053     _date = None
00054 
00055     ObjectDeleted = ObjectDeleted
00056     ObjectMoved = ObjectMoved
00057 
00058     security = ClassSecurityInfo()
00059     security.setDefaultAccess('allow')
00060 
00061     def __init__(self, object, workflow, status=None, transition=None,
00062                  old_state=None, new_state=None, kwargs=None):
00063         if kwargs is None:
00064             kwargs = {}
00065         else:
00066             # Don't allow mutation
00067             kwargs = SafeMapping(kwargs)
00068         if status is None:
00069             tool = aq_parent(aq_inner(workflow))
00070             status = tool.getStatusOf(workflow.id, object)
00071             if status is None:
00072                 status = {}
00073         if status:
00074             # Don't allow mutation
00075             status = SafeMapping(status)
00076         self.object = object
00077         self.workflow = workflow
00078         self.old_state = old_state
00079         self.new_state = new_state
00080         self.transition = transition
00081         self.status = status
00082         self.kwargs = kwargs
00083 
00084     def __getitem__(self, name):
00085         if name[:1] != '_' and hasattr(self, name):
00086             return getattr(self, name)
00087         raise KeyError, name
00088 
00089     def getHistory(self):
00090         wf = self.workflow
00091         tool = aq_parent(aq_inner(wf))
00092         wf_id = wf.id
00093         h = tool.getHistoryOf(wf_id, self.object)
00094         if h:
00095             return map(lambda dict: dict.copy(), h)  # Don't allow mutation
00096         else:
00097             return ()
00098 
00099     def getPortal(self):
00100         ob = aq_inner(self.object)
00101         while ob is not None:
00102             if ISiteRoot.providedBy(ob):
00103                 return ob
00104             if getattr(ob, '_isPortalRoot', None) is not None:
00105                 # BBB
00106                 warn("The '_isPortalRoot' marker attribute for site "
00107                      "roots is deprecated and will be removed in "
00108                      "CMF 2.3;  please mark the root object with "
00109                      "'ISiteRoot' instead.",
00110                      DeprecationWarning, stacklevel=2)
00111                 return ob
00112             ob = aq_parent(ob)
00113         return None
00114 
00115     def getDateTime(self):
00116         date = self._date
00117         if not date:
00118             date = self._date = DateTime()
00119         return date
00120 
00121 Globals.InitializeClass(StateChangeInfo)
00122 
00123 
00124 def createExprContext(sci):
00125     '''
00126     An expression context provides names for TALES expressions.
00127     '''
00128     ob = sci.object
00129     wf = sci.workflow
00130     container = aq_parent(aq_inner(ob))
00131     data = {
00132         'here':         ob,
00133         'object':       ob,
00134         'container':    container,
00135         'folder':       container,
00136         'nothing':      None,
00137         'root':         ob.getPhysicalRoot(),
00138         'request':      getattr( ob, 'REQUEST', None ),
00139         'modules':      SecureModuleImporter,
00140         'user':         getSecurityManager().getUser(),
00141         'state_change': sci,
00142         'transition':   sci.transition,
00143         'status':       sci.status,
00144         'kwargs':       sci.kwargs,
00145         'workflow':     wf,
00146         'scripts':      wf.scripts,
00147         }
00148     return getEngine().getContext(data)
00149