def __init__(self, policy_id, predicate='', mtime_func='', max_age_secs=None, no_cache=0, no_store=0, must_revalidate=0): if not predicate: predicate = 'python:1' if not mtime_func: mtime_func = 'content/modified' if max_age_secs is not None: max_age_secs = int(max_age_secs) self._policy_id = policy_id self._predicate = Expression(text=predicate) self._mtime_func = Expression(text=mtime_func) self._max_age_secs = max_age_secs self._no_cache = int(no_cache) self._no_store = int(no_store) self._must_revalidate = int(must_revalidate)
def updatePreviewActions(self, preview_actions): """Now a misnomer: actually updates preview, normal, and scaling data""" action_map = {} for a in preview_actions: portal_type = a.get('portal_type', '') preview = a.get('expression', '') normal = a.get('normal', None) if normal: normal = Expression(normal) scalefield = a.get('scalefield', 'image') defscale = a.get('defscale', 'image_preview') classes = a.get('classes', '') if isinstance(classes, basestring): classes = classes.split('\n') classes = tuple(classes) mediatype = a.get('mediatype', 'image') if not portal_type: continue action_map[portal_type] = { 'expression': Expression(preview), 'normal': normal, 'scalefield': scalefield, 'defscale': defscale, 'classes': classes, 'mediatype': mediatype, } self._preview_actions = action_map
def test_listActionInformationActions(self): # Check that listFilteredActionsFor works for objects that return # ActionInformation objects tool = self.tool tool._actions = ( ActionInformation(id='folderContents', title='Folder contents', action=Expression(text='string:' '${folder_url}/folder_contents'), icon_expr=Expression(text='string:' '${folder_url}/icon.gif'), condition=Expression(text='python: ' 'folder is not object'), permissions=('List folder contents',), category='folder', link_target='_top', visible=1),) newSecurityManager(None, OmnipotentUser().__of__(self.app.acl_users)) self.assertEqual(tool.listFilteredActionsFor(self.app.foo), {'workflow': [], 'user': [], 'object': [], 'folder': [{'id': 'folderContents', 'url': 'http://nohost/folder_contents', 'icon': 'http://nohost/icon.gif', 'title': 'Folder contents', 'description': '', 'visible': True, 'available': True, 'allowed': True, 'category': 'folder', 'link_target': '_top'}], 'global': []})
def test_listActionInformationActions(self): # Check that listFilteredActionsFor works for objects that return # ActionInformation objects root = self.root tool = self.tool tool._actions = (ActionInformation( id='folderContents', title='Folder contents', action=Expression(text='string:' '${folder_url}/folder_contents'), icon_expr=Expression(text='string:' '${folder_url}/icon.gif'), condition=Expression(text='python: ' 'folder is not object'), permissions=('List folder contents', ), category='folder', visible=1), ) self.assertEqual( tool.listFilteredActionsFor(root.foo), { 'workflow': [], 'user': [], 'object': [], 'folder': [{ 'id': 'folderContents', 'url': 'http://nohost/folder_contents', 'icon': 'http://nohost/icon.gif', 'title': 'Folder contents', 'description': '', 'visible': True, 'available': True, 'allowed': True, 'category': 'folder' }], 'global': [] })
def testSimplestExpression(self): context = self.portal self.assertTrue(self.tool.evaluateExpression( Expression('python:1'), context)) self.assertFalse(self.tool.evaluateExpression( Expression('python:0'), context)) self.assertTrue(self.tool.evaluateExpression( Expression('python:0+1'), context))
def testSimplestExpression(self): context = self.portal self.failUnless( self.tool.evaluateExpression(Expression('python:1'), context)) self.failIf( self.tool.evaluateExpression(Expression('python:0'), context)) self.failUnless( self.tool.evaluateExpression(Expression('python:0+1'), context))
def fixActionsForType(portal_type, typesTool): if 'actions' in portal_type.installMode: typeInfo = getattr(typesTool, portal_type.portal_type, None) if typeInfo is None: return if hasattr(portal_type, 'actions'): # Look for each action we define in portal_type.actions in # typeInfo.action replacing it if its there and just # adding it if not # rr: this is now trial-and-error programming # I really don't know what's going on here # most importantly I don't know why the default # actions are not set in some cases :-( # (maybe they are removed afterwards sometimes???) # if getattr(portal_type,'include_default_actions', True): if True: default = [ ActionInformation(**action) for action in base_factory_type_information[0]['actions'] ] next = list(typeInfo._actions) all = next + default new = [a.clone() for a in all] else: # If no standard actions are wished don't display them new = [] for action in portal_type.actions: # DM: "Expression" derives from "Persistent" and # we must not put persistent objects into class attributes. # Thus, copy "action" action = action.copy() hits = [a for a in new if a.id == action['id']] # Change action and condition into expressions, if # they are still strings if 'action' in action and \ type(action['action']) in (type(''), type(u'')): action['action'] = Expression(action['action']) if 'condition' in action and \ type(action['condition']) in (type(''), type(u'')): action['condition'] = Expression(action['condition']) if 'name' in action: action['title'] = action['name'] del action['name'] if hits: hits[0].__dict__.update(action) else: new.append(ActionInformation(**action)) typeInfo._actions = tuple(new) typeInfo._p_changed = True if hasattr(portal_type, 'factory_type_information'): typeInfo.__dict__.update(portal_type.factory_type_information) typeInfo._p_changed = True
def customizeTypes(self, portal): types_tool = getToolByName(portal, 'portal_types') # New 'Paper' type based on file types_tool.manage_addTypeInformation( id='Paper', add_meta_type="Factory-based Type Information", typeinfo_name="CMFDefault: Portal File") paper = getattr(types_tool, 'Paper') actions = paper._cloneActions() for a in actions: if a.id == 'edit': a.action = Expression('string:${object_url}/paper_edit_form') paper._actions = actions # New 'Presentation' type based on file types_tool.manage_addTypeInformation( id='Presentation', add_meta_type="Factory-based Type Information", typeinfo_name="CMFDefault: Portal File") pres = getattr(types_tool, 'Presentation') pres.manage_changeProperties(content_icon='ppt_icon.png') actions = pres._cloneActions() for a in actions: if a.id == 'edit': a.action = Expression( 'string:${object_url}/presentation_edit_form') pres._actions = actions # New 'Blog Item' type based on 'News Item' types_tool.manage_addTypeInformation( id='Blog Item', add_meta_type="Factory-based Type Information", typeinfo_name="CMFDefault: News Item") blog = getattr(types_tool, 'Blog Item') actions = blog._cloneActions() for a in actions: if a.id == 'view': a.action = Expression('string:${object_url}/blogitem_view') blog._actions = actions # New 'Blog Folder' type based on 'Folder' types_tool.manage_addTypeInformation( id='Blog Folder', add_meta_type="Factory-based Type Information", typeinfo_name="CMFPlone: Plone Folder") bf = getattr(types_tool, 'Blog Folder') actions = bf._cloneActions() for a in actions: if a.id == 'folderlisting': a.visible = 0 if a.id == 'view': a.action = Expression('string:${folder_url}/blogfolder_view') a.category = 'object' bf._actions = actions
def addAction( self, id, name, action, condition='', permission='', category='Plone', visible=1, appId=None, imageUrl=None, icon_expr='', description='', REQUEST=None, ): """ Add an action to our list. """ if not name: raise ValueError('A name is required.') a_expr = action and Expression(text=str(action)) or '' c_expr = condition and Expression(text=str(condition)) or '' if type(permission) != type(()): permission = permission and (str(permission), ) or () if imageUrl: log_deprecated("The imageUrl parameter of the control panel " "tool's addAction/registerConfiglet method has " "been deprecated and will be removed in Plone 5. " "Please use the icon_expr parameter instead.") icon_expr = 'string:${portal_url}/%s' % imageUrl new_actions = self._cloneActions() new_action = PloneConfiglet( id=str(id), title=name, action=a_expr, condition=c_expr, permissions=permission, category=str(category), visible=int(visible), appId=appId, description=description, icon_expr=icon_expr, ) new_actions.append(new_action) self._actions = tuple(new_actions) if REQUEST is not None: return self.manage_editActionsForm(REQUEST, manage_tabs_message='Added.')
def ActionProviderBase_extractAction( self, properties, index ): """ Extract an ActionInformation from the funky form properties. """ id = str( properties.get( 'id_%d' % index, '' ) ) title = str( properties.get( 'title_%d' % index, '' ) ) description = str( properties.get( 'description_%d' % index, '' ) ) action = str( properties.get( 'action_%d' % index, '' ) ) icon = str( properties.get( 'icon_%d' % index, '' ) ) condition = str( properties.get( 'condition_%d' % index, '' ) ) category = str( properties.get( 'category_%d' % index, '' )) visible = properties.get( 'visible_%d' % index, 0 ) permissions = properties.get( 'permission_%d' % index, () ) priority = float( properties.get( 'priority_%d' % index, 1.0 )) if not title: raise ValueError('A title is required.') if action is not '': action = Expression( text=action ) if icon is not '': icon = Expression( text=icon ) if condition is not '': condition = Expression( text=condition ) if category == '': category = 'object' if type( visible ) is not type( 0 ): try: visible = int( visible ) except TypeError: visible = 0 if type( permissions ) is type( '' ): permissions = ( permissions, ) if type( priority ) is not type(1.0): priority = float(priority) return ActionInformation( id=id , title=title , description=description , action=action , icon=icon , condition=condition , permissions=permissions , category=category , visible=visible , priority=priority )
def test_Condition(self): portal = self.portal folder = self.folder object = self.object ai = ActionInformation(id='view', title='View', action=Expression(text='view'), condition=Expression(text='member'), category='global', visible=1) ec = createExprContext(folder, portal, object) self.failIf(ai.testCondition(ec))
def set_guards_to_inactive_workflow(): wtool = api.get_tool('portal_workflow') workflow = wtool.getWorkflowById('bika_inactive_workflow') deactivate = workflow.transitions['deactivate'] deactivate_guard = deactivate.getGuard() deactivate_guard.expr = Expression('python:here.guard_deactivate_transition()') deactivate.guard = deactivate_guard activate = workflow.transitions['activate'] activate_guard = activate.getGuard() activate_guard.expr = Expression('python:here.guard_activate_transition()') activate.guard = activate_guard
def test_Condition(self): portal = self.portal folder = self.folder object = self.object ai = self._makeOne(id='view', title='View', action=Expression(text='view'), condition=Expression(text='member'), category='global', visible=True) ec = createExprContext(folder, portal, object) self.assertFalse(ai.testCondition(ec))
def setUp(self): SecurityTest.setUp(self) app = self.app app._setObject('portal', DummyContent('portal', url='url_portal')) self.portal = app.portal self.folder = DummyContent('foo', url='url_foo') self.object = DummyContent('bar', url='url_bar') self.ai = ActionInformation(id='view', title='View', action=Expression(text='view'), condition=Expression(text='member'), category='global', visible=1)
def test_construction_with_Expressions(self): ai = ActionInformation(id='view', title='View', action=Expression(text='view'), condition=Expression(text='member'), category='global', visible=0) self.assertEqual(ai.getId(), 'view') self.assertEqual(ai.Title(), 'View') self.assertEqual(ai.Description(), '') self.assertEqual(ai.getCondition(), 'member') self.assertEqual(ai.getActionExpression(), 'string:view') self.assertEqual(ai.getVisibility(), 0) self.assertEqual(ai.getCategory(), 'global') self.assertEqual(ai.getPermissions(), ())
def setActionExpression(self, action): if action and isinstance(action, six.string_types): if not action.startswith('string:') and \ not action.startswith('python:'): action = 'string:${object_url}/%s' % action action = Expression(action) self.action = action
def canBeCreatedInLicence(self, obj): """ Creation condition computed by evaluating the TAL expression stored in TALCondition field """ res = True # At least for now # Check condition TALCondition = self.getTALCondition().strip() if TALCondition: data = { 'nothing': None, 'portal': api.portal.get(), 'object': obj, 'event': self, 'request': api.portal.getRequest(), 'here': obj, 'licence': obj, } ctx = getEngine().getContext(data) try: res = Expression(TALCondition)(ctx) except Exception, e: logger.warn( "The condition '%s' defined for element at '%s' is wrong! Message is : %s" % (TALCondition, obj.absolute_url(), e)) res = False
def setProperties(self, description, default_value='', default_expr='', for_catalog=0, for_status=0, update_always=0, props=None, REQUEST=None): ''' ''' self.description = str(description) self.default_value = str(default_value) if default_expr: self.default_expr = Expression(default_expr) else: self.default_expr = None g = Guard() if g.changeFromProperties(props or REQUEST): self.info_guard = g else: self.info_guard = None self.for_catalog = bool(for_catalog) self.for_status = bool(for_status) self.update_always = bool(update_always) if REQUEST is not None: return self.manage_properties(REQUEST, 'Properties changed.')
def setIconExpression(self, icon_expr): if icon_expr and isinstance(icon_expr, basestring): if ( not icon_expr.startswith('string:') and not icon_expr.startswith('python:') ): icon_expr = 'string:${object_url}/%s' % icon_expr icon_expr = Expression( icon_expr ) self.icon_expr = icon_expr
def setActionExpression(self, action): if action and isinstance(action, basestring): if ( not action.startswith('string:') and not action.startswith('python:') ): action = 'string:${object_url}/%s' % action action = Expression( action ) self.action = action
def _setPropValue(self, id, value): self._wrapperCheck(value) if isinstance(value, list): value = tuple(value) setattr(self, id, value) if value and id.endswith('_expr'): setattr( self, '%s_object' % id, Expression(value) )
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. We will make sure that each non None constraint_definition is satisfied (unicity) This Constraint use portal_catalog """ error_list = PropertyExistenceConstraint._checkConsistency(self, obj, fixit=fixit) attribute_name = self.getConstraintProperty() expression_criterion_dict = self.getFilterParameter() message_id = None mapping = dict(attribute_name=attribute_name) #Evaluate expression_criterion_dict expression = Expression(expression_criterion_dict) econtext = createExpressionContext(obj) criterion_dict = expression(econtext) # Add uid in criterion keys to avoid fetching current object. criterion_dict['query'] = NegatedQuery(Query(uid=obj.getUid())) portal = obj.getPortalObject() result = portal.portal_catalog.countResults(**criterion_dict)[0][0] if result >= 1: mapping['value'] = criterion_dict.get(attribute_name) message_id = 'message_invalid_attribute_unicity' # Generate error if message_id is not None: error_list.append(self._generateError(obj, self._getMessage(message_id), mapping)) return error_list
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. """ # import this later to prevent circular import from Products.ERP5Type.Utils import createExpressionContext error_list = [] expression_text = self.constraint_definition['expression'] expression = Expression(expression_text) econtext = createExpressionContext(obj) try: if not expression(econtext): error_list.append( self._generateError( obj, self._getMessage('message_expression_false'))) except (ConflictError, CompilerError): raise except Exception, e: LOG('ERP5Type', PROBLEM, 'TALESConstraint error on "%s" on %s' % (self.constraint_definition['expression'], obj), error=sys.exc_info()) error_list.append( self._generateError( obj, self._getMessage('message_expression_error'), mapping=dict(error_text=str(e))))
def available_widgets(self): types_tool = getToolByName(self, "portal_types") types = types_tool.listTypeInfo() available = [] for type_info in types: dotted = getattr(type_info, 'klass', None) if not dotted: continue package, klass = dotted.rsplit('.', 1) try: __import__(package) except ImportError: continue klass = getattr(sys.modules[package], klass, None) if not ICompositionFragment.implementedBy(klass): continue expression = Expression(type_info.icon_expr) expression_context = getExprContext(self) icon = expression(expression_context) available.append({ 'portal_type': type_info.id, 'icon': icon, 'title': type_info.title, 'description': type_info.description }) return available
def getInfoData(self): """ Get the data needed to create an ActionInfo. """ lazy_keys = ['available', 'allowed'] lazy_map = {} lazy_map['id'] = self.getId() lazy_map['category'] = 'folder/add' lazy_map['title'] = self.Title() lazy_map['description'] = self.Description() if self.add_view_expr: lazy_map['url'] = self.add_view_expr_object lazy_keys.append('url') else: lazy_map['url'] = '' if self.icon_expr: lazy_map['icon'] = self.icon_expr_object lazy_keys.append('icon') elif self.content_icon: lazy_map['icon'] = Expression('string:${portal_url}/%s' % self.content_icon) lazy_keys.append('icon') else: lazy_map['icon'] = '' lazy_map['visible'] = True lazy_map['available'] = self._checkAvailable lazy_map['allowed'] = self._checkAllowed return (lazy_map, lazy_keys)
def test_DuplicateActions(self): """ Check that listFilteredActionsFor filters out duplicate actions. """ root = self.root tool = self.tool action = ActionInformation(id='test', title='Test', action=Expression(text='string: a_url'), condition='', permissions=(), category='object', visible=1) tool._actions = [action, action] self.tool.action_providers = ('portal_actions', ) self.assertEqual( tool.listFilteredActionsFor(root)['object'], [{ 'permissions': (), 'id': 'test', 'url': ' a_url', 'name': 'Test', 'visible': 1, 'category': 'object' }])
def setIconExpression(self, icon_expr): if icon_expr and isinstance(icon_expr, six.string_types): if not icon_expr.startswith('string:') and \ not icon_expr.startswith('python:'): icon_expr = 'string:${object_url}/%s' % icon_expr icon_expr = Expression(icon_expr) self.icon_expr = icon_expr
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. We will make sure that each non None constraint_definition is satisfied (unicity) This Constraint use portal_catalog """ errors = PropertyExistence._checkConsistency(self, obj, fixit=fixit) for attribute_name, expression_criterion_dict in self.constraint_definition.items(): message_id = None mapping = dict(attribute_name=attribute_name) #Evaluate expression_criterion_dict expression = Expression(expression_criterion_dict) from Products.ERP5Type.Utils import createExpressionContext econtext = createExpressionContext(obj) criterion_dict = expression(econtext) from Products.ZSQLCatalog.SQLCatalog import Query, NegatedQuery # Add uid in criterion keys to avoid fetching current object. criterion_dict['query'] = NegatedQuery(Query(uid=obj.getUid())) portal = obj.getPortalObject() result = portal.portal_catalog.countResults(**criterion_dict)[0][0] if result >= 1: mapping['value'] = criterion_dict.get(attribute_name) message_id = 'message_invalid_attribute_unicity' # Generate error if message_id is not None: errors.append(self._generateError(obj, self._getMessage(message_id), mapping)) return errors
def test_Condition_PathExpression(self): portal = self.portal folder = self.folder object = self.object manage_addPythonScript(self.root, 'test_script') script = self.root.test_script script.ZPythonScript_edit('', 'return context.getId()') ai = self._makeOne(id='view', title='View', action=Expression(text='view'), condition=Expression(text='portal/test_script'), category='global', visible=True) ec = createExprContext(folder, portal, object) self.assertTrue(ai.testCondition(ec))
def changeFromProperties(self, props): ''' Returns 1 if changes were specified. ''' if props is None: return 0 res = 0 s = props.get('guard_permissions', None) if s: res = 1 p = [ permission.strip() for permission in s.split(';') ] self.permissions = tuple(p) s = props.get('guard_roles', None) if s: res = 1 r = [ role.strip() for role in s.split(';') ] self.roles = tuple(r) s = props.get('guard_groups', None) if s: res = 1 g = [ group.strip() for group in s.split(';') ] self.groups = tuple(g) s = props.get('guard_expr', None) if s: res = 1 self.expr = Expression(s) return res
def update(self): try: topMenu = aq_acquire(self.context, 'top-menu') except AttributeError: topMenu = 'topnavigation' self.topnavigation = self.context_state.actions().get(topMenu, None) # URL that contains the section self.container_url = None if self.topnavigation: matches = [] for t in self.topnavigation: portal_url = self.context.portal_url() context_url = self.context.absolute_url() menu_url = t.get('url') urls = [menu_url] # Handle additional URLs configured in portal_actions if t.get('additional_urls'): econtext = getExprContext(self.context) for u in t.get('additional_urls'): try: url_expr = Expression(u) urls.append(url_expr.__call__(econtext)) except: pass for t_url in urls: # Remove trailing / to normalize if t_url.endswith("/"): t_url = t_url[0:-1] if portal_url.endswith("/"): portal_url = portal_url[0:-1] if context_url.endswith("/"): context_url = context_url[0:-1] if portal_url != t_url and context_url.startswith(t_url): matches.append(menu_url) # Remove trailing slash if matches: self.container_url = sorted(matches, key=lambda x:len(x), reverse=True)[0]
def _importRole(self, role_property_dict): """Import a role from a BT or from an old portal type""" import erp5 RoleInformation = getattr(erp5.portal_type, 'Role Information') role = RoleInformation(self.generateNewId()) for k, v in role_property_dict.iteritems(): if k == 'condition': if isinstance(v, Expression): v = v.text if not v: continue v = Expression(v) elif k == 'priority': continue elif k == 'id': k, v = 'role_name', tuple(x.strip() for x in v.split(';')) elif k in ('base_category', 'category'): k, v = 'role_' + k, tuple(y for y in (x.strip() for x in v) if y) elif k == 'base_category_script': k = 'role_base_category_script_id' setattr(role, k, v) role.uid = None return self[self._setObject(role.id, role, set_owner=0)]
def _importRole(self, role_property_dict): """Import a role from a BT or from an old portal type""" import erp5 RoleInformation = getattr(erp5.portal_type, "Role Information") role = RoleInformation(self.generateNewId()) for k, v in role_property_dict.iteritems(): if k == "condition": if isinstance(v, Expression): v = v.text if not v: continue v = Expression(v) elif k == "priority": continue elif k == "id": k, v = "role_name", tuple(x.strip() for x in v.split(";")) elif k in ("base_category", "category"): k, v = "role_" + k, tuple(y for y in (x.strip() for x in v) if y) elif k == "base_category_script": k = "role_base_category_script_id" setattr(role, k, v) role.uid = None return self[self._setObject(role.id, role, set_owner=0)]