From e2f7b3fbb09ad87b05c5fdfb01056b4ab68aa176 Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Sat, 25 Apr 2015 00:44:59 +0300 Subject: [PATCH 1/9] generate action and role id with prefix ( 'action_REFERENCE_%d' and 'role_%d' ) change of copy, move, create object code ( now constructor of object can change generated id) transparently migrate of old id regenerate id if reference is changed --- product/ERP5/Document/BusinessTemplate.py | 36 ++++-- product/ERP5Type/CopySupport.py | 6 +- product/ERP5Type/Core/ActionInformation.py | 3 +- product/ERP5Type/Core/Folder.py | 2 +- product/ERP5Type/Core/RoleInformation.py | 3 +- product/ERP5Type/ERP5Type.py | 2 +- product/ERP5Type/gen_id_from_reference.py | 122 +++++++++++++++++++++ 7 files changed, 158 insertions(+), 16 deletions(-) create mode 100644 product/ERP5Type/gen_id_from_reference.py diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py index 6b70b10c3da..def7b115939 100644 --- a/product/ERP5/Document/BusinessTemplate.py +++ b/product/ERP5/Document/BusinessTemplate.py @@ -6065,20 +6065,17 @@ Business Template is a set of definitions, such as skins, portal types and categ bt_portal_types_id_list = list(self.getTemplatePortalTypeIdList()) bt_portal_type_roles_list = list(self.getTemplatePortalTypeRoleList()) bt_wf_chain_list = list(self.getTemplatePortalTypeWorkflowChainList()) + bt_path_list = list(self.getTemplatePathList()) for id in bt_portal_types_id_list: portal_type = ttool.getTypeInfo(id) if portal_type is None: continue - if portal_type.getRoleInformationList(): - if id not in bt_portal_type_roles_list: - bt_portal_type_roles_list.append(id) allowed_content_type_list = [] hidden_content_type_list = [] property_sheet_list = [] base_category_list = [] - action_list = [] if hasattr(portal_type, 'allowed_content_types'): allowed_content_type_list = portal_type.allowed_content_types if hasattr(portal_type, 'hidden_content_type_list'): @@ -6087,8 +6084,6 @@ Business Template is a set of definitions, such as skins, portal types and categ property_sheet_list = portal_type.property_sheet_list if hasattr(portal_type, 'base_category_list'): base_category_list = portal_type.base_category_list - for action in portal_type.getActionInformationList(): - action_list.append(action.getReference()) for a_id in allowed_content_type_list: allowed_id = id+' | '+a_id @@ -6110,10 +6105,29 @@ Business Template is a set of definitions, such as skins, portal types and categ if base_cat_id not in bt_base_category_list: bt_base_category_list.append(base_cat_id) - for act_id in action_list: - action_id = id+' | '+act_id - if action_id not in bt_action_list: - bt_action_list.append(action_id) + for action in portal_type.getActionInformationList(): + act_id = action.getId() + act_ref = action.getReference() + try: + bt_action_list.remove(id + ' | ' + act_id) + except ValueError: + pass + try: + bt_action_list.remove(id + ' | ' + act_ref) + except ValueError: + pass + action_path = "portal_types/" + id + "/" + act_id + if action_path not in bt_path_list: + bt_path_list.append(action_path) + + for role in portal_type.getRoleInformationList(): + role_path = "portal_types/" + id + "/" + role.getId() + if role_path not in bt_path_list: + bt_path_list.append(role_path) + try: + bt_portal_type_roles_list.remove(id) + except ValueError: + pass for workflow_id in [chain for chain in wtool.getChainFor(id) if chain != '(Default)']: @@ -6127,6 +6141,7 @@ Business Template is a set of definitions, such as skins, portal types and categ bt_base_category_list.sort() bt_action_list.sort() bt_wf_chain_list.sort() + bt_path_list.sort() self.setTemplatePortalTypeWorkflowChainList(bt_wf_chain_list) self.setTemplatePortalTypeRoleList(bt_portal_type_roles_list) @@ -6135,6 +6150,7 @@ Business Template is a set of definitions, such as skins, portal types and categ self.setTemplatePortalTypePropertySheetList(bt_property_sheet_list) self.setTemplatePortalTypeBaseCategoryList(bt_base_category_list) self.setTemplateActionPathList(bt_action_list) + self.setTemplatePathList(bt_path_list) security.declareProtected(Permissions.AccessContentsInformation, diff --git a/product/ERP5Type/CopySupport.py b/product/ERP5Type/CopySupport.py index 7d0101fc3b4..93408b0ff16 100644 --- a/product/ERP5Type/CopySupport.py +++ b/product/ERP5Type/CopySupport.py @@ -561,8 +561,9 @@ class CopyContainer: ob=ob._getCopy(self) orig_id=ob.getId() id=self._get_id(ob.getId()) - result.append({'id':orig_id, 'new_id':id}) ob._setId(id) + id = ob.id + result.append({'id':orig_id, 'new_id':id}) if not is_indexable: ob._setNonIndexable() self._setObject(id, ob) @@ -597,9 +598,10 @@ class CopyContainer: ob = aq_base(ob) orig_id=id id=self._get_id(id) - result.append({'id':orig_id, 'new_id':id }) ob._setId(id) + id = ob.id + result.append({'id':orig_id, 'new_id':id }) if not is_indexable: ob._setNonIndexable() self._setObject(id, ob, set_owner=0) diff --git a/product/ERP5Type/Core/ActionInformation.py b/product/ERP5Type/Core/ActionInformation.py index 1db697464a6..128e246ac85 100644 --- a/product/ERP5Type/Core/ActionInformation.py +++ b/product/ERP5Type/Core/ActionInformation.py @@ -35,9 +35,10 @@ from Products.CMFCore.Expression import Expression from Products.ERP5Type import interfaces, Permissions, PropertySheet from Products.ERP5Type.Permissions import AccessContentsInformation from Products.ERP5Type.XMLObject import XMLObject +from Products.ERP5Type.gen_id_from_reference import GenerateIdFromReferenceMixin -class ActionInformation(XMLObject): +class ActionInformation(GenerateIdFromReferenceMixin('action'), XMLObject): """ ActionInformation is an ERP5 type which will eventually replace respective ActionInformation from CMF. """ diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py index 4305c0287fd..eb77e0a818b 100644 --- a/product/ERP5Type/Core/Folder.py +++ b/product/ERP5Type/Core/Folder.py @@ -163,7 +163,7 @@ class FolderMixIn(ExtensionClass.Base): temp_object=temp_object or temp_container, **kw) if temp_container: - container._setObject(new_id, new_instance.aq_base) + container._setObject(new_instance.id, new_instance.aq_base) return new_instance security.declareProtected( diff --git a/product/ERP5Type/Core/RoleInformation.py b/product/ERP5Type/Core/RoleInformation.py index 7198c20367a..b44a253fe66 100644 --- a/product/ERP5Type/Core/RoleInformation.py +++ b/product/ERP5Type/Core/RoleInformation.py @@ -40,9 +40,10 @@ from Products.ERP5Type.ERP5Type \ import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT from Products.ERP5Type.Permissions import AccessContentsInformation from Products.ERP5Type.XMLObject import XMLObject +from Products.ERP5Type.gen_id_from_reference import GenerateIdFromReferenceMixin -class RoleInformation(XMLObject): +class RoleInformation(GenerateIdFromReferenceMixin('role'), XMLObject): """ Represent a role definition. Roles definitions defines local roles on ERP5Type documents. They are diff --git a/product/ERP5Type/ERP5Type.py b/product/ERP5Type/ERP5Type.py index ed001faa19d..56bca8d30bd 100644 --- a/product/ERP5Type/ERP5Type.py +++ b/product/ERP5Type/ERP5Type.py @@ -401,7 +401,7 @@ class ERP5TypeInformation(XMLObject, ob.setDefaultReindexParameterDict(reindex_kw) if is_indexable is not None: base_ob.isIndexable = is_indexable - container._setObject(id, base_ob) + container._setObject(base_ob.id, base_ob) # if no activity tool, the object has already an uid if getattr(base_ob, 'uid', None) is None: ob.uid = portal.portal_catalog.newUid() diff --git a/product/ERP5Type/gen_id_from_reference.py b/product/ERP5Type/gen_id_from_reference.py new file mode 100644 index 00000000000..8c28f9791b0 --- /dev/null +++ b/product/ERP5Type/gen_id_from_reference.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +############################################################################## +# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved. +# Julien Muchembled , +# Boris Kocherov +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly advised to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################## + +from Products.CMFActivity.Errors import ActivityPendingError +from Products.ERP5Type.CopySupport import CopyContainer +from zLOG import LOG, WARNING + +def GenerateIdFromReferenceMixin(prefix): + prefix_ = prefix + "_" + class GenerateIdAsReferenceMixin(object): + + def __init__(self, ob_id): + if not ob_id.startswith(prefix_): + ob_id = prefix_ + ob_id + self.id = ob_id + + def cb_isMoveable(self): + return self.cb_userHasCopyOrMovePermission() + + def __migrate(self): + self._setIdByRefernce() + + def _genIdByRefernce(self, old_id=None, reference=None): + if not old_id: + old_id = self.id + if not reference: + reference = getattr(self, 'reference', None) + if reference: + base_id = new_id = "_".join((prefix, reference)) + else: + base_id = new_id = prefix + if old_id != new_id and not old_id.startswith(new_id + "_"): + parent = self.getParentValue() + if not reference: + new_id = base_id + "_" + old_id + int_ob_id = 0 + while 0 <= int_ob_id <= 100: + if new_id not in parent: + break + int_ob_id += 1 + new_id = base_id + "_%d" % (int_ob_id,) + if new_id in parent: + int_ob_id = parent.generateNewId() + new_id = base_id + "_%d" % (int_ob_id,) + if new_id in parent: + LOG("GenerateIdFromReferenceMixin", WARNING, "Skipping migration id of %r in %r" + " %s, due to ID conflict" % (new_id, parent.getId(), parent.getPortalType())) + else: + return new_id + return None + + def _setIdByRefernce(self, old_id=None, reference=None): + new_id = self._genIdByRefernce(old_id, reference) + if new_id: + try: + self.setId(new_id) + except ActivityPendingError: + parent = self.getParentValue() + LOG("GenerateIdFromReferenceMixin", WARNING, "Skipping update id of %r in %r" + " %s, due to pending activities" % (old_id, parent.getId(), parent.getPortalType())) + + def getId(self, default=None): + """ + It's only for migration. + it' can be removed if all instances updating + """ + ob_id = self._baseGetId(default) + migration = getattr(self, '_v_idmigration', False) + if not migration and not ob_id.startswith(prefix_): + self._v_idmigration = True + new_id = self._genIdByRefernce(old_id=ob_id) + try: + self.setId(new_id) + except ActivityPendingError: + parent = self.getParentValue() + LOG("GenerateIdFromReferenceMixin", WARNING, "Skipping migration of %r in %r" + " %s, due to pending activities" % (old_id, parent.getId(), parent.getPortalType())) + return new_id + return ob_id + + def _setId(self, ob_id): + """ + update id for moved and copied objects + """ + if not ob_id.startswith(prefix_): + ob_id = prefix_ + ob_id + return CopyContainer._setId(self, ob_id) + + def _setReference(self, value): + """ + update id if reference change + """ + self._setIdByRefernce(reference=value) + self._baseSetReference(value) + + return GenerateIdAsReferenceMixin -- 2.30.9 From 6b4922933f33f9b8ff4bf9a69cc2bb57297fb68e Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Sat, 25 Apr 2015 00:43:47 +0300 Subject: [PATCH 2/9] ERP5ish portal_actions and actions in portal_actions add ActionProviderBase for share code between ActionsTool and DynamicType remove monkey patch ActionsTool adapt BusinesTemplates import/export for ERP5portal_actions change bootstrap erp5: create ERP5portal_action instead of CMFportal_actions transparently migrate erp5_core and erp5_promise: convert CMFaction to ERP5Action --- .../action_check_site_consistency.xml} | 36 ++--- bt5/erp5_promise/bt/template_action_path_list | 1 - bt5/erp5_promise/bt/template_path_list | 1 + product/ERP5/Document/BusinessTemplate.py | 10 +- product/ERP5/ERP5Site.py | 7 +- .../portal_types/Actions%20Tool/view.xml | 85 ++++++++++ .../portal_actions/action_bt_tool.xml} | 36 ++--- .../portal_actions/action_category_tool.xml} | 36 ++--- .../portal_actions/action_component_tool.xml} | 36 +++-- .../portal_actions/action_create_module.xml} | 36 ++--- .../portal_actions/action_history.xml} | 36 ++--- .../portal_actions/action_list_ui.xml} | 36 ++--- .../portal_actions/action_login.xml} | 36 +++-- .../portal_actions/action_logout.xml} | 36 +++-- .../portal_actions/action_make_template.xml} | 36 +++-- .../portal_actions/action_mass_workflow.xml} | 36 +++-- .../portal_actions/action_metadata.xml} | 36 ++--- .../portal_actions/action_module_view.xml} | 36 +++-- .../action_portal_alarms_action.xml} | 36 ++--- .../portal_actions/action_preferences.xml} | 36 +++-- .../action_property_sheet_tool.xml} | 36 ++--- .../portal_actions/action_search.xml} | 36 ++--- .../portal_actions/action_sort_on.xml} | 36 ++--- .../portal_actions/action_types_tool.xml} | 36 ++--- .../portal_actions/action_undo.xml} | 36 +++-- .../portal_categories/action_type/global.xml | 38 +++++ .../action_type/object_sort.xml | 40 +++++ .../action_type/object_ui.xml | 39 +++++ .../portal_categories/action_type/user.xml | 38 +++++ .../action_type/workflow.xml | 41 +++++ .../allowed_content_types.xml | 3 + .../portal_types/Actions%20Tool.xml | 133 +++++++++++++++ .../erp5_core/bt/template_action_path_list | 20 +-- .../bootstrap/erp5_core/bt/template_path_list | 19 +++ ...late_portal_type_allowed_content_type_list | 1 + .../erp5_core/bt/template_portal_type_id_list | 1 + product/ERP5Type/ActionProviderBase.py | 153 ++++++++++++++++++ product/ERP5Type/ERP5Type.py | 122 +------------- product/ERP5Type/Tool/ActionsTool.py | 146 +++++++++++++++++ product/ERP5Type/Tool/TypesTool.py | 8 +- product/ERP5Type/ZopePatch.py | 1 - product/ERP5Type/__init__.py | 5 +- product/ERP5Type/patches/ActionsTool.py | 112 ------------- 43 files changed, 1132 insertions(+), 612 deletions(-) rename bt5/erp5_promise/{ActionTemplateItem/portal_types/portal_actions/check_site_consistency.xml => PathTemplateItem/portal_actions/action_check_site_consistency.xml} (76%) delete mode 100644 bt5/erp5_promise/bt/template_action_path_list create mode 100644 product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/Actions%20Tool/view.xml rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/bt_tool.xml => PathTemplateItem/portal_actions/action_bt_tool.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/category_tool.xml => PathTemplateItem/portal_actions/action_category_tool.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/component_tool.xml => PathTemplateItem/portal_actions/action_component_tool.xml} (82%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/create_module.xml => PathTemplateItem/portal_actions/action_create_module.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/history.xml => PathTemplateItem/portal_actions/action_history.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/list_ui.xml => PathTemplateItem/portal_actions/action_list_ui.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_membership/login.xml => PathTemplateItem/portal_actions/action_login.xml} (81%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_membership/logout.xml => PathTemplateItem/portal_actions/action_logout.xml} (81%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/make_template.xml => PathTemplateItem/portal_actions/action_make_template.xml} (81%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/mass_workflow.xml => PathTemplateItem/portal_actions/action_mass_workflow.xml} (81%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/metadata.xml => PathTemplateItem/portal_actions/action_metadata.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/module_view.xml => PathTemplateItem/portal_actions/action_module_view.xml} (81%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/portal_alarms_action.xml => PathTemplateItem/portal_actions/action_portal_alarms_action.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_membership/preferences.xml => PathTemplateItem/portal_actions/action_preferences.xml} (81%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/property_sheet_tool.xml => PathTemplateItem/portal_actions/action_property_sheet_tool.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/search.xml => PathTemplateItem/portal_actions/action_search.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/sort_on.xml => PathTemplateItem/portal_actions/action_sort_on.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_actions/types_tool.xml => PathTemplateItem/portal_actions/action_types_tool.xml} (75%) rename product/ERP5/bootstrap/erp5_core/{ActionTemplateItem/portal_types/portal_undo/undo.xml => PathTemplateItem/portal_actions/action_undo.xml} (81%) create mode 100644 product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/global.xml create mode 100644 product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_sort.xml create mode 100644 product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_ui.xml create mode 100644 product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/user.xml create mode 100644 product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/workflow.xml create mode 100644 product/ERP5/bootstrap/erp5_core/PortalTypeTemplateItem/portal_types/Actions%20Tool.xml create mode 100644 product/ERP5Type/ActionProviderBase.py create mode 100644 product/ERP5Type/Tool/ActionsTool.py diff --git a/bt5/erp5_promise/ActionTemplateItem/portal_types/portal_actions/check_site_consistency.xml b/bt5/erp5_promise/PathTemplateItem/portal_actions/action_check_site_consistency.xml similarity index 76% rename from bt5/erp5_promise/ActionTemplateItem/portal_types/portal_actions/check_site_consistency.xml rename to bt5/erp5_promise/PathTemplateItem/portal_actions/action_check_site_consistency.xml index 323409eee8c..227a7760a7d 100644 --- a/bt5/erp5_promise/ActionTemplateItem/portal_types/portal_actions/check_site_consistency.xml +++ b/bt5/erp5_promise/PathTemplateItem/portal_actions/action_check_site_consistency.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - global + action_permission + + + Manage portal + + - condition - + categories + + + action_type/global + + description - icon - + float_index + 1.6 id - check_site_consistency + action_check_site_consistency - permissions - - - Manage portal - - - - - priority - 1.6 + reference + check_site_consistency title diff --git a/bt5/erp5_promise/bt/template_action_path_list b/bt5/erp5_promise/bt/template_action_path_list deleted file mode 100644 index 8251b7c0352..00000000000 --- a/bt5/erp5_promise/bt/template_action_path_list +++ /dev/null @@ -1 +0,0 @@ -portal_actions | check_site_consistency \ No newline at end of file diff --git a/bt5/erp5_promise/bt/template_path_list b/bt5/erp5_promise/bt/template_path_list index 9b38cc156c6..791d5f08e58 100644 --- a/bt5/erp5_promise/bt/template_path_list +++ b/bt5/erp5_promise/bt/template_path_list @@ -1,3 +1,4 @@ +portal_actions/action_check_site_consistency portal_alarms/promise_certificate_autority_tool portal_alarms/promise_conversion_server portal_alarms/promise_install_bt5 diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py index def7b115939..1b36a3f4dcb 100644 --- a/product/ERP5/Document/BusinessTemplate.py +++ b/product/ERP5/Document/BusinessTemplate.py @@ -29,6 +29,7 @@ import fnmatch, gc, glob, imp, os, re, shutil, sys, time, tarfile from collections import defaultdict +from Products.CMFCore.interfaces import IActionsTool from Shared.DC.ZRDB import Aqueduct from Shared.DC.ZRDB.Connection import Connection as RDBConnection from Products.ERP5Type.DiffUtils import DiffFile @@ -3204,7 +3205,8 @@ class ActionTemplateItem(ObjectTemplateItem): Gets action copy from action provider given the action id or reference """ # Several tools still use CMF actions - if interfaces.ITypeProvider.providedBy(obj.getParentValue()): + if interfaces.ITypeProvider.providedBy(obj.getParentValue()) \ + or IActionsTool.providedBy(obj): return self._getPortalTypeActionCopy(obj, value) else: return self._getPortalToolActionCopy(obj, context, value) @@ -3250,7 +3252,8 @@ class ActionTemplateItem(ObjectTemplateItem): path, id = id.rsplit('/', 1) container = p.unrestrictedTraverse(path) - if interfaces.ITypeProvider.providedBy(aq_parent(aq_inner(container))): + if interfaces.ITypeProvider.providedBy(aq_parent(aq_inner(container)))\ + or IActionsTool.providedBy(container): # XXX future BT should use 'reference' instead of 'id' reference = getattr(obj, 'reference', None) or obj.id portal_type_dict.setdefault(path, {})[reference] = obj @@ -3328,7 +3331,8 @@ class ActionTemplateItem(ObjectTemplateItem): obj = p.unrestrictedTraverse(relative_url, None) # Several tools still use CMF actions if obj is not None: - is_new_action = interfaces.ITypeProvider.providedBy(obj.getParentValue()) + is_new_action = interfaces.ITypeProvider.providedBy(obj.getParentValue()) or \ + IActionsTool.providedBy(obj) key = is_new_action and 'reference' or 'id' else: relative_url, key, value = self._splitPath(id) diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py index da3a39735e1..b08a2c8e361 100644 --- a/product/ERP5/ERP5Site.py +++ b/product/ERP5/ERP5Site.py @@ -1668,6 +1668,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin): if tool_id in ('portal_categories', ): tool = tool.activate() tool.migrateToPortalTypeClass(tool_id not in ( + 'portal_actions', 'portal_activities', 'portal_simulation', 'portal_templates', 'portal_trash')) if tool_id in ('portal_trash',): @@ -1707,7 +1708,6 @@ class PortalGenerator: """Set up initial tools""" addCMFCoreTool = p.manage_addProduct['CMFCore'].manage_addTool - addCMFCoreTool('CMF Actions Tool', None) addCMFCoreTool('CMF Catalog', None) addCMFCoreTool('CMF Member Data Tool', None) addCMFCoreTool('CMF Skins Tool', None) @@ -1885,7 +1885,7 @@ class ERP5Generator(PortalGenerator): """ Set up initial tools. """ - if not 'portal_actions' in p.objectIds(): + if not 'portal_skins' in p.objectIds(): PortalGenerator.setupTools(self, p) # It is better to remove portal_catalog @@ -1919,6 +1919,7 @@ class ERP5Generator(PortalGenerator): addERP5Tool(p, 'portal_password', 'Password Tool') addERP5Tool(p, 'portal_introspections', 'Introspection Tool') addERP5Tool(p, 'portal_acknowledgements', 'Acknowledgement Tool') + addERP5Tool(p, 'portal_actions', 'Actions Tool') # Add ERP5Type Tool addERP5Tool(p, 'portal_caches', 'Cache Tool') @@ -2020,8 +2021,6 @@ class ERP5Generator(PortalGenerator): removeActionsFromTool(p.portal_membership, ('addFavorite', 'mystuff', 'favorites', 'logged_in', 'manage_members')) - # actions tool - removeActionsFromTool(p.portal_actions, ('folderContents',)) # properties tool removeActionsFromTool(p.portal_properties, ('configPortal',)) # remove unused action providers diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/Actions%20Tool/view.xml b/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/Actions%20Tool/view.xml new file mode 100644 index 00000000000..7576391e042 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/Actions%20Tool/view.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_view + + + + + category + object_view + + + condition + + + + description + + + + + + icon + + + + id + view + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + View + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BaseType_viewAction + + + + + diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/bt_tool.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_bt_tool.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/bt_tool.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_bt_tool.xml index 4c6e55ef4e8..980853fb6ce 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/bt_tool.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_bt_tool.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - global + action_permission + + + Manage portal + + - condition - + categories + + + action_type/global + + description - icon - + float_index + 1.0 id - bt_tool + action_bt_tool - permissions - - - Manage portal - - - - - priority - 1.0 + reference + bt_tool title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/category_tool.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_category_tool.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/category_tool.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_category_tool.xml index 4e0185ee860..d854205109c 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/category_tool.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_category_tool.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - global + action_permission + + + Manage portal + + - condition - + categories + + + action_type/global + + description - icon - + float_index + 2.0 id - category_tool + action_category_tool - permissions - - - Manage portal - - - - - priority - 2.0 + reference + category_tool title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/component_tool.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_component_tool.xml similarity index 82% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/component_tool.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_component_tool.xml index d3dbd5d8e5c..e78784a41b8 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/component_tool.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_component_tool.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - global + action_permission + + + Manage portal + + + + + categories + + + action_type/global + + condition @@ -27,24 +39,16 @@ - icon - + float_index + 3.0 id - component_tool + action_component_tool - permissions - - - Manage portal - - - - - priority - 3.0 + reference + component_tool title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/create_module.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_create_module.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/create_module.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_create_module.xml index 70e6aafb2c0..9957fd3dc24 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/create_module.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_create_module.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - global + action_permission + + + Manage portal + + - condition - + categories + + + action_type/global + + description - icon - + float_index + 3.0 id - create_module + action_create_module - permissions - - - Manage portal - - - - - priority - 3.0 + reference + create_module title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/history.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_history.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/history.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_history.xml index f26e71c9828..f413d8987a9 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/history.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_history.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - object_view + action_permission + + + View + + - condition - + categories + + + action_type/object_view + + description - icon - + float_index + 99.0 id - history + action_history - permissions - - - View - - - - - priority - 99.0 + reference + history title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/list_ui.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_list_ui.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/list_ui.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_list_ui.xml index d6c043eaaac..264674ef18f 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/list_ui.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_list_ui.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - object_ui + action_permission + + + View + + - condition - + categories + + + action_type/object_ui + + description - icon - + float_index + 100.0 id - list_ui + action_list_ui - permissions - - - View - - - - - priority - 100.0 + reference + list_ui title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/login.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_login.xml similarity index 81% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/login.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_login.xml index 47dcc47b2b2..b6ee567c298 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/login.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_login.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - user + action_permission + + + View + + + + + categories + + + action_type/user + + condition @@ -27,24 +39,16 @@ Click here to Login - icon - + float_index + 2.0 id - login + action_login - permissions - - - View - - - - - priority - 2.0 + reference + login title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/logout.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_logout.xml similarity index 81% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/logout.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_logout.xml index 08742b2ab29..3e07b714778 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/logout.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_logout.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - user + action_permission + + + View + + + + + categories + + + action_type/user + + condition @@ -27,24 +39,16 @@ Click here to logout - icon - + float_index + 2.0 id - logout + action_logout - permissions - - - View - - - - - priority - 2.0 + reference + logout title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/make_template.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_make_template.xml similarity index 81% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/make_template.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_make_template.xml index 8565fc41fe5..33dd7095a33 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/make_template.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_make_template.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - object_action + action_permission + + + View + + + + + categories + + + action_type/object_action + + condition @@ -27,24 +39,16 @@ - icon - + float_index + 101.0 id - make_template + action_make_template - permissions - - - View - - - - - priority - 101.0 + reference + make_template title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/mass_workflow.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_mass_workflow.xml similarity index 81% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/mass_workflow.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_mass_workflow.xml index 74930b66be5..a9187e88c95 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/mass_workflow.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_mass_workflow.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - workflow + action_permission + + + View + + + + + categories + + + action_type/workflow + + condition @@ -27,24 +39,16 @@ - icon - + float_index + 100.0 id - mass_workflow + action_mass_workflow - permissions - - - View - - - - - priority - 100.0 + reference + mass_workflow title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/metadata.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_metadata.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/metadata.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_metadata.xml index 3bdc7900493..8db9e25d527 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/metadata.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_metadata.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - object_view + action_permission + + + Manage properties + + - condition - + categories + + + action_type/object_view + + description - icon - + float_index + 100.0 id - metadata + action_metadata - permissions - - - Manage properties - - - - - priority - 100.0 + reference + metadata title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/module_view.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_module_view.xml similarity index 81% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/module_view.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_module_view.xml index b358e7e1617..cba761ceb6d 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/module_view.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_module_view.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - object_view + action_permission + + + Manage portal + + + + + categories + + + action_type/object_view + + condition @@ -27,24 +39,16 @@ - icon - + float_index + 100.0 id - module_view + action_module_view - permissions - - - Manage portal - - - - - priority - 100.0 + reference + module_view title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/portal_alarms_action.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_portal_alarms_action.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/portal_alarms_action.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_portal_alarms_action.xml index fd5562cb1d2..8c83a6d23d6 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/portal_alarms_action.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_portal_alarms_action.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - global + action_permission + + + Manage portal + + - condition - + categories + + + action_type/global + + description - icon - + float_index + 6.5 id - portal_alarms_action + action_portal_alarms_action - permissions - - - Manage portal - - - - - priority - 6.5 + reference + portal_alarms_action title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/preferences.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_preferences.xml similarity index 81% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/preferences.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_preferences.xml index bb9caaf078b..aa451e1da73 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_membership/preferences.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_preferences.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - user + action_permission + + + View + + + + + categories + + + action_type/user + + condition @@ -27,24 +39,16 @@ Change your user preferences - icon - + float_index + 1.0 id - preferences + action_preferences - permissions - - - View - - - - - priority - 1.0 + reference + preferences title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/property_sheet_tool.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_property_sheet_tool.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/property_sheet_tool.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_property_sheet_tool.xml index 8d1657463a2..db741cba6f1 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/property_sheet_tool.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_property_sheet_tool.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - global + action_permission + + + Manage portal + + - condition - + categories + + + action_type/global + + description - icon - + float_index + 5.0 id - property_sheet_tool + action_property_sheet_tool - permissions - - - Manage portal - - - - - priority - 5.0 + reference + property_sheet_tool title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/search.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_search.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/search.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_search.xml index f868cd2a912..f42d7972564 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/search.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_search.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - object_search + action_permission + + + View + + - condition - + categories + + + action_type/object_search + + description - icon - + float_index + 100.0 id - search + action_search - permissions - - - View - - - - - priority - 100.0 + reference + search title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/sort_on.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_sort_on.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/sort_on.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_sort_on.xml index cc89439c9f4..6f563b0ab75 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/sort_on.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_sort_on.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - object_sort + action_permission + + + View + + - condition - + categories + + + action_type/object_sort + + description - icon - + float_index + 100.0 id - sort_on + action_sort_on - permissions - - - View - - - - - priority - 100.0 + reference + sort_on title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/types_tool.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_types_tool.xml similarity index 75% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/types_tool.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_types_tool.xml index 2f92177440a..3cba3b8dfd7 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_actions/types_tool.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_types_tool.xml @@ -2,7 +2,7 @@ - + @@ -13,36 +13,36 @@ - category - global + action_permission + + + Manage portal + + - condition - + categories + + + action_type/global + + description - icon - + float_index + 4.0 id - types_tool + action_types_tool - permissions - - - Manage portal - - - - - priority - 4.0 + reference + types_tool title diff --git a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_undo/undo.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_undo.xml similarity index 81% rename from product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_undo/undo.xml rename to product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_undo.xml index 00753657740..4da37522534 100644 --- a/product/ERP5/bootstrap/erp5_core/ActionTemplateItem/portal_types/portal_undo/undo.xml +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_actions/action_undo.xml @@ -2,7 +2,7 @@ - + @@ -13,8 +13,20 @@ - category - global + action_permission + + + List undoable changes + + + + + categories + + + action_type/global + + condition @@ -27,24 +39,16 @@ - icon - + float_index + 10.0 id - undo + action_undo - permissions - - - List undoable changes - - - - - priority - 10.0 + reference + undo title diff --git a/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/global.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/global.xml new file mode 100644 index 00000000000..da2da01fb66 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/global.xml @@ -0,0 +1,38 @@ + + + + + + + + + + categories + + + action_type/global + + + + + description + + + + + + id + global + + + portal_type + Category + + + title + global + + + + + diff --git a/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_sort.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_sort.xml new file mode 100644 index 00000000000..6a8dbaf7f9a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_sort.xml @@ -0,0 +1,40 @@ + + + + + + + + + + categories + + + action_type/user + action_type/object_ui + action_type/object_sort + + + + + description + + + + + + id + object_sort + + + portal_type + Category + + + title + object_sort + + + + + diff --git a/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_ui.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_ui.xml new file mode 100644 index 00000000000..a24a9e47cbf --- /dev/null +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/object_ui.xml @@ -0,0 +1,39 @@ + + + + + + + + + + categories + + + action_type/user + action_type/object_ui + + + + + description + + + + + + id + object_ui + + + portal_type + Category + + + title + object_ui + + + + + diff --git a/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/user.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/user.xml new file mode 100644 index 00000000000..9bc76be9412 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/user.xml @@ -0,0 +1,38 @@ + + + + + + + + + + categories + + + action_type/user + + + + + description + + + + + + id + user + + + portal_type + Category + + + title + user + + + + + diff --git a/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/workflow.xml b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/workflow.xml new file mode 100644 index 00000000000..c703a76a1cd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_core/PathTemplateItem/portal_categories/action_type/workflow.xml @@ -0,0 +1,41 @@ + + + + + + + + + + categories + + + action_type/user + action_type/object_ui + action_type/object_sort + action_type/workflow + + + + + description + + + + + + id + workflow + + + portal_type + Category + + + title + workflow + + + + + diff --git a/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml b/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml index ca0f166cac7..6f59ca7ee6e 100644 --- a/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml +++ b/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml @@ -1,4 +1,7 @@ + + Action Information + Active Process diff --git a/product/ERP5/bootstrap/erp5_core/PortalTypeTemplateItem/portal_types/Actions%20Tool.xml b/product/ERP5/bootstrap/erp5_core/PortalTypeTemplateItem/portal_types/Actions%20Tool.xml new file mode 100644 index 00000000000..446069eee75 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_core/PortalTypeTemplateItem/portal_types/Actions%20Tool.xml @@ -0,0 +1,133 @@ + + + + + + + + + + _property_domain_dict + + + + short_title + + AAAAAAAAAAI= + + + + title + + AAAAAAAAAAM= + + + + + + + acquire_local_roles + 0 + + + content_icon + + + + + + content_meta_type + ERP5 Types Tool + + + description + The Types Tool centralises all portal type definitions. + + + factory + addFolder + + + filter_content_types + 1 + + + group_list + + + + + + id + Actions Tool + + + init_script + + + + + + permission + + + + + + title + + + + type_class + ActionsTool + + + type_interface + + + + + + type_mixin + + + + + + + + + + + + + + + domain_name + erp5_ui + + + property_name + short_title + + + + + + + + + + + + domain_name + erp5_ui + + + property_name + title + + + + + diff --git a/product/ERP5/bootstrap/erp5_core/bt/template_action_path_list b/product/ERP5/bootstrap/erp5_core/bt/template_action_path_list index dc7d30b92a3..5b4fe8e7ed3 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/template_action_path_list +++ b/product/ERP5/bootstrap/erp5_core/bt/template_action_path_list @@ -1,5 +1,6 @@ Acquired Property | view Action Information | view +Actions Tool | view Active Process | view Activity Tool | view Activity Tool | watch_report @@ -135,22 +136,3 @@ Trash Folder | view Trash Tool | view Types Tool | view ZODB Continuous Increasing Id Generator | view -portal_actions | bt_tool -portal_actions | category_tool -portal_actions | component_tool -portal_actions | create_module -portal_actions | history -portal_actions | list_ui -portal_actions | make_template -portal_actions | mass_workflow -portal_actions | metadata -portal_actions | module_view -portal_actions | portal_alarms_action -portal_actions | property_sheet_tool -portal_actions | search -portal_actions | sort_on -portal_actions | types_tool -portal_membership | login -portal_membership | logout -portal_membership | preferences -portal_undo | undo \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_core/bt/template_path_list b/product/ERP5/bootstrap/erp5_core/bt/template_path_list index 88d0f27d7d2..da1c28772a4 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/template_path_list +++ b/product/ERP5/bootstrap/erp5_core/bt/template_path_list @@ -1,3 +1,22 @@ +portal_actions/action_bt_tool +portal_actions/action_category_tool +portal_actions/action_component_tool +portal_actions/action_create_module +portal_actions/action_history +portal_actions/action_list_ui +portal_actions/action_login +portal_actions/action_logout +portal_actions/action_make_template +portal_actions/action_mass_workflow +portal_actions/action_metadata +portal_actions/action_module_view +portal_actions/action_portal_alarms_action +portal_actions/action_preferences +portal_actions/action_property_sheet_tool +portal_actions/action_search +portal_actions/action_sort_on +portal_actions/action_types_tool +portal_actions/action_undo portal_alarms/expired_password_alarm portal_caches/erp5_content_long portal_caches/erp5_content_long/default_ram_cache diff --git a/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list b/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list index 680082233be..ff49c391ea7 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list +++ b/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list @@ -1,3 +1,4 @@ +Actions Tool | Action Information Activity Tool | Active Process Alarm Tool | Alarm Applied Rule | Simulation Movement diff --git a/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_id_list b/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_id_list index 4ea29617e76..b7c221649e6 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_id_list +++ b/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_id_list @@ -1,6 +1,7 @@ Acknowledgement Tool Acquired Property Action Information +Actions Tool Active Process Activity Tool Alarm diff --git a/product/ERP5Type/ActionProviderBase.py b/product/ERP5Type/ActionProviderBase.py new file mode 100644 index 00000000000..c35d980b053 --- /dev/null +++ b/product/ERP5Type/ActionProviderBase.py @@ -0,0 +1,153 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. +# 2006 Nexedi +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +from Products.ERP5Type.Cache import CachingMethod +from Products.ERP5Type.Globals import InitializeClass +from AccessControl import ClassSecurityInfo +from Products.ERP5Type.Utils import deprecated +from Products.ERP5Type import Permissions + + +class ActionProviderBase(object): + """ + Provide Translation Tabs and management methods for PropertyTranslationDomain + """ + security = ClassSecurityInfo() + + security.declarePrivate('getCacheableActionList') + def getCacheableActionList(self): + """Return a cacheable list of enabled actions""" + return [action.getCacheableAction() + for action in self.getActionInformationList() + if action.isVisible()] + + def _getActionList(self): + action_list = self.getCacheableActionList() + # This sort is a duplicate of calculation with what is done + # on portal_actions.listFilteredActionsFor . But getDefaultViewFor + # needs the sort here. This needs to be reviewed, because it is possible + # to define in portal_actions some actions that will have higher + # priorities than actions defined on portal types + action_list.sort(key=lambda x:x['priority']) + return action_list + _getActionList = CachingMethod(_getActionList, + id='getActionList', + cache_factory='erp5_content_long', + cache_id_generator=lambda method_id, *args: method_id) + + security.declarePrivate('getActionList') + def getActionList(self): + """Return the list of enabled actions from cache, sorted by priority""" + return self._getActionList(self, scope=self.id) + + security.declareProtected(Permissions.ModifyPortalContent, + 'clearGetActionListCache') + def clearGetActionListCache(self): + """Clear a cache of _getRawActionInformationList.""" + self._getActionList.delete(scope=self.id) + + security.declareProtected(Permissions.AccessContentsInformation, + 'getActionInformationList') + def getActionInformationList(self): + """Return all Action Information objects stored on this portal type""" + return self.objectValues(meta_type='ERP5 Action Information') + + # + # XXX CMF compatibility + # + + def _importOldAction(self, old_action): + """Convert a CMF action to an ERP5 action + + This is used to update an existing site or to import a BT. + """ + import erp5.portal_type + ActionInformation = getattr(erp5.portal_type, 'Action Information') + old_action = old_action.__getstate__() + action_type = old_action.pop('category', None) + action_id = "action_%s" % old_action['id'] + action = ActionInformation(action_id) + for k, v in old_action.iteritems(): + if k in ('action', 'condition', 'icon'): + if not v: + continue + v = v.__class__(v.text) + setattr(action, {'id': 'reference', + 'priority': 'float_index', + 'permissions': 'action_permission', + }.get(k, k), v) + action.uid = None + action = self[self._setObject(action.id, action, set_owner=0)] + #action = self[_eventLessSetObject(self)(action.id, action, set_owner=0)] + if action_type: + action._setCategoryMembership('action_type', action_type) + return action + + def _exportOldAction(self, action): + """Convert an ERP5 action to a CMF action + + This is used to export a BT. + """ + from Products.CMFCore.ActionInformation import ActionInformation + old_action = ActionInformation(action.reference, + category=action.getActionType(), + priority=action.getFloatIndex(), + permissions=tuple(action.getActionPermissionList())) + for k, v in action.__dict__.iteritems(): + if k in ('action', 'condition', 'icon'): + if not v: + continue + v = v.__class__(v.text) + elif k in ('id', 'float_index', 'action_permission', 'reference'): + continue + setattr(old_action, k, v) + return old_action + + security.declareProtected(Permissions.AddPortalContent, 'addAction') + @deprecated + def addAction(self, id, name, action, condition, permission, category, + icon=None, visible=1, priority=1.0, REQUEST=None, + description=None): + """ + Not used + """ + if isinstance(permission, basestring): + permission = permission, + self.newContent("action_%s" % (id,), + portal_type='Action Information', + reference=id, + title=name, + action=action, + condition=condition, + permission_list=permission, + action_type=category, + icon=icon, + visible=visible, + float_index=priority, + description=description) + + security.declareProtected(Permissions.ModifyPortalContent, 'deleteActions') + @deprecated + def deleteActions(self, selections=(), REQUEST=None): + action_list = self.listActions() + self.manage_delObjects([action_list[x].id for x in selections]) + + security.declarePrivate('listActions') + @deprecated + def listActions(self, info=None, object=None): + """ List all the actions defined by a provider.""" + return sorted(self.getActionInformationList(), + key=lambda x: (x.getFloatIndex(), x.getId())) + +InitializeClass(ActionProviderBase) + diff --git a/product/ERP5Type/ERP5Type.py b/product/ERP5Type/ERP5Type.py index 56bca8d30bd..4cc0164f380 100644 --- a/product/ERP5Type/ERP5Type.py +++ b/product/ERP5Type/ERP5Type.py @@ -20,6 +20,7 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +from Products.ERP5Type.ActionProviderBase import ActionProviderBase import zope.interface from Products.ERP5Type.Globals import InitializeClass @@ -35,7 +36,6 @@ from Products.ERP5Type.Base import getClassPropertyList from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.Utils import deprecated, createExpressionContext from Products.ERP5Type.XMLObject import XMLObject -from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.dynamic.accessor_holder import getPropertySheetValueList, \ getAccessorHolderList from Products.ERP5Type.TransactionalVariable import getTransactionalVariable @@ -212,6 +212,7 @@ class LocalRoleAssignorMixIn(object): InitializeClass(LocalRoleAssignorMixIn) class ERP5TypeInformation(XMLObject, + ActionProviderBase, FactoryTypeInformation, LocalRoleAssignorMixIn, TranslationProviderBase): @@ -647,44 +648,6 @@ class ERP5TypeInformation(XMLObject, __traceback_info__ = self.getId(), target return ob.restrictedTraverse(target) - security.declarePrivate('getCacheableActionList') - def getCacheableActionList(self): - """Return a cacheable list of enabled actions""" - return [action.getCacheableAction() - for action in self.getActionInformationList() - if action.isVisible()] - - def _getActionList(self): - action_list = self.getCacheableActionList() - # This sort is a duplicate of calculation with what is done - # on portal_actions.listFilteredActionsFor . But getDefaultViewFor - # needs the sort here. This needs to be reviewed, because it is possible - # to define in portal_actions some actions that will have higher - # priorities than actions defined on portal types - action_list.sort(key=lambda x:x['priority']) - return action_list - _getActionList = CachingMethod(_getActionList, - id='getActionList', - cache_factory='erp5_content_long', - cache_id_generator=lambda method_id, *args: method_id) - - security.declarePrivate('getActionList') - def getActionList(self): - """Return the list of enabled actions from cache, sorted by priority""" - return self._getActionList(self, scope=self.id) - - security.declareProtected(Permissions.ModifyPortalContent, - 'clearGetActionListCache') - def clearGetActionListCache(self): - """Clear a cache of _getRawActionInformationList.""" - self._getActionList.delete(scope=self.id) - - security.declareProtected(Permissions.AccessContentsInformation, - 'getActionInformationList') - def getActionInformationList(self): - """Return all Action Information objects stored on this portal type""" - return self.objectValues(meta_type='ERP5 Action Information') - def getIcon(self): try: return self.getTypeIcon() @@ -741,85 +704,4 @@ class ERP5TypeInformation(XMLObject, def getHiddenContentTypeList(self): return self.getTypeHiddenContentTypeList(()) - # Compatibitility code for actions - - security.declareProtected(Permissions.AddPortalContent, 'addAction') - @deprecated - def addAction(self, id, name, action, condition, permission, category, - icon=None, visible=1, priority=1.0, REQUEST=None, - description=None): - if isinstance(permission, basestring): - permission = permission, - if isinstance(action, str) and action[:7] not in ('string:', 'python:'): - value = 'string:${object_url}/' + value - self.newContent(portal_type='Action Information', - reference=id, - title=name, - action=action, - condition=condition, - permission_list=permission, - action_type=category, - icon=icon, - visible=visible, - float_index=priority, - description=description) - - security.declareProtected(Permissions.ModifyPortalContent, 'deleteActions') - @deprecated - def deleteActions(self, selections=(), REQUEST=None): - action_list = self.listActions() - self.manage_delObjects([action_list[x].id for x in selections]) - - security.declarePrivate('listActions') - @deprecated - def listActions(self, info=None, object=None): - """ List all the actions defined by a provider.""" - return sorted(self.getActionInformationList(), - key=lambda x: (x.getFloatIndex(), x.getId())) - - def _importOldAction(self, old_action): - """Convert a CMF action to an ERP5 action - - This is used to update an existing site or to import a BT. - """ - import erp5.portal_type - ActionInformation = getattr(erp5.portal_type, 'Action Information') - old_action = old_action.__getstate__() - action_type = old_action.pop('category', None) - action = ActionInformation(self.generateNewId()) - for k, v in old_action.iteritems(): - if k in ('action', 'condition', 'icon'): - if not v: - continue - v = v.__class__(v.text) - setattr(action, {'id': 'reference', - 'priority': 'float_index', - 'permissions': 'action_permission', - }.get(k, k), v) - action.uid = None - action = self[self._setObject(action.id, action, set_owner=0)] - if action_type: - action._setCategoryMembership('action_type', action_type) - return action - - def _exportOldAction(self, action): - """Convert an ERP5 action to a CMF action - - This is used to export a BT. - """ - from Products.CMFCore.ActionInformation import ActionInformation - old_action = ActionInformation(action.reference, - category=action.getActionType(), - priority=action.getFloatIndex(), - permissions=tuple(action.getActionPermissionList())) - for k, v in action.__dict__.iteritems(): - if k in ('action', 'condition', 'icon'): - if not v: - continue - v = v.__class__(v.text) - elif k in ('id', 'float_index', 'action_permission', 'reference'): - continue - setattr(old_action, k, v) - return old_action - InitializeClass( ERP5TypeInformation ) diff --git a/product/ERP5Type/Tool/ActionsTool.py b/product/ERP5Type/Tool/ActionsTool.py new file mode 100644 index 00000000000..a3c67f62ae1 --- /dev/null +++ b/product/ERP5Type/Tool/ActionsTool.py @@ -0,0 +1,146 @@ +############################################################################## +# +# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved. +# Jean-Paul Smets-Solanes +# Julien Muchembled +# Boris Kocherov +# +# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +import logging + +logger = logging.getLogger(__name__) + +from Products.CMFCore.interfaces import IActionProvider, IActionsTool +import zope.interface +from AccessControl import ClassSecurityInfo +from Products.CMFCore import ActionsTool as CMFCore_ActionsToolModule +from Products.ERP5Type.Tool.BaseTool import BaseTool +from Products.ERP5Type.ActionProviderBase import ActionProviderBase +from Products.ERP5Type import Permissions +from zLOG import LOG, WARNING + +CMFCore_ActionsTool = CMFCore_ActionsToolModule.ActionsTool + +def _eventLessSetObject(container): + _setObject = container._setObject + return lambda *args, **kw: _setObject(suppress_events=True, *args, **kw) + +def checkAndCreateActionToolBaseCategory(parent): + if not parent.portal_categories.hasObject('action_type'): + # Required to generate ActionInformation.getActionType accessor. + import erp5 + action_type = getattr(erp5.portal_type, 'Base Category')('action_type') + action_type.uid = None + _eventLessSetObject(parent.portal_categories)(action_type.id, action_type) + +class ActionsTool(BaseTool, ActionProviderBase, CMFCore_ActionsTool): + """Provides a configurable registry of portal content types + """ + id = "portal_actions" + + meta_type = 'ERP5 Actions Tool' + portal_type = 'Actions Tool' + allowed_types = () + + zope.interface.implements(IActionsTool) + + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + def migrateNonProviders(self): + portal_actions_path = '/'.join(self.getPhysicalPath()) + portal = self.getPortalObject() + action_providers = list(self.action_providers) + for provider_name in self.listActionProviders(): + provider = getattr(portal, provider_name) + if (getattr(provider, '_actions', ()) and + getattr(provider, 'listActionInfos', None) is None ): + logger.info('migrating actions from %r to %r', + portal_actions_path, '/'.join(provider.getPhysicalPath())) + for old_action in provider._actions: + self._importOldAction(old_action) + del provider._actions + if (getattr(provider, 'listActionInfos', None) is None and + getattr(provider, 'getActionListFor', None) is None and + not (IActionProvider.providedBy(provider))): + action_providers.remove(provider_name) + self.action_providers = tuple(action_providers) + + security.declarePrivate('getActionListFor') + def getActionListFor(self, ob=None): + """Return all actions applicable to the object""" + old_actions = self._actions or () + if old_actions: + LOG('OldActionsTool', WARNING, "Converting portal_actions...") + checkAndCreateActionToolBaseCategory(self) + for action_info in old_actions: + self._importOldAction(action_info) + LOG('OldActionsTool', WARNING, "... portal_actions converted.") + self._actions = () + if ob is not None: + return (action.getCacheableAction() for action in self.objectValues()) + return () + + def listFilteredActionsFor(self, object=None): + """ List all actions available to the user. + + This patch removes inclusion of actions from the object itself. + It was never used and now, it breaks objects inside Types Tool. + + It also checks for a new ERP5-only actions API (getActionListFor), but + this API should be moved to listActionInfos() of each tool so as not to + create duplicate code paths that are sources of bugs. + + Finally, this patch detects tools that are no longer action providers and + invokes the migration of their actions to portal_actions + """ + actions = [] + + portal = self.getPortalObject() + # Include actions from specific tools. + for provider_name in self.listActionProviders(): + provider = getattr(portal, provider_name) + if hasattr(provider, 'getActionListFor'): + from Products.ERP5Type.Utils import createExpressionContext + + ec = createExpressionContext(object) + actions.extend(action.cook(ec) + for action in provider.getActionListFor(object) + if action.test(ec)) + elif IActionProvider.providedBy(provider): + actions.extend(provider.listActionInfos(object=object)) + else: + # This should only be triggered once + # We're in 2.12 and we need to migrate objects that are no longer + # IActionProviders: + self.migrateNonProviders() + # Recompute from beginning + return self.listFilteredActionsFor(object=object) + + actions.sort(key=lambda x: x.get('priority', 0)) + # Reorganize the actions by category. + filtered_actions = {'user': [], + 'folder': [], + 'object': [], + 'global': [], + 'workflow': [], + } + + for action in actions: + filtered_actions.setdefault(action['category'], []).append(action) + + return filtered_actions + +# Change the CMFCore's ActionsTool to automatically migrate to ERP5Actions's +# ActionsTool +CMFCore_ActionsToolModule.ActionsTool = ActionsTool diff --git a/product/ERP5Type/Tool/TypesTool.py b/product/ERP5Type/Tool/TypesTool.py index 37ae34ba71d..894e4c921df 100644 --- a/product/ERP5Type/Tool/TypesTool.py +++ b/product/ERP5Type/Tool/TypesTool.py @@ -18,6 +18,7 @@ import imp, sys, warnings import inspect from itertools import chain +from Products.ERP5Type.Tool.ActionsTool import checkAndCreateActionToolBaseCategory import zope.interface from Acquisition import aq_base from AccessControl import ClassSecurityInfo @@ -367,12 +368,7 @@ class OldTypesTool(OFSFolder): del parent.portal_types _eventLessSetObject(parent)(TypesTool.id, types_tool, set_owner=0) types_tool = types_tool.__of__(parent) - if not parent.portal_categories.hasObject('action_type'): - # Required to generate ActionInformation.getActionType accessor. - import erp5 - action_type = getattr(erp5.portal_type, 'Base Category')('action_type') - action_type.uid = None - parent.portal_categories._setObject(action_type.id, action_type) + checkAndCreateActionToolBaseCategory(parent) for type_info in self.objectValues(): self._migratePortalType(types_tool, type_info) types_tool.activate()._finalizeMigration() diff --git a/product/ERP5Type/ZopePatch.py b/product/ERP5Type/ZopePatch.py index bd0d636659c..a2f705a2d49 100644 --- a/product/ERP5Type/ZopePatch.py +++ b/product/ERP5Type/ZopePatch.py @@ -43,7 +43,6 @@ from Products.ERP5Type.patches import States from Products.ERP5Type.patches import FSZSQLMethod from Products.ERP5Type.patches import ActionInformation from Products.ERP5Type.patches import ActionProviderBase -from Products.ERP5Type.patches import ActionsTool from Products.ERP5Type.patches import CookieCrumbler from Products.ERP5Type.patches import PropertySheets from Products.ERP5Type.patches import CMFCoreSkinnable diff --git a/product/ERP5Type/__init__.py b/product/ERP5Type/__init__.py index 5b6691247aa..e97c73f1c01 100644 --- a/product/ERP5Type/__init__.py +++ b/product/ERP5Type/__init__.py @@ -89,7 +89,7 @@ def initialize( context ): # Import Product Components from Tool import (CacheTool, MemcachedTool, SessionTool, TypesTool, WebServiceTool, PropertySheetTool, - ComponentTool) + ComponentTool, ActionsTool) import Document from Base import Base import XMLObject @@ -107,7 +107,8 @@ def initialize( context ): TypesTool.TypesTool, WebServiceTool.WebServiceTool, PropertySheetTool.PropertySheetTool, - ComponentTool.ComponentTool + ComponentTool.ComponentTool, + ActionsTool.ActionsTool, ) # Do initialization step initializeProduct(context, this_module, globals(), diff --git a/product/ERP5Type/patches/ActionsTool.py b/product/ERP5Type/patches/ActionsTool.py index d8ac5f446d1..e69de29bb2d 100644 --- a/product/ERP5Type/patches/ActionsTool.py +++ b/product/ERP5Type/patches/ActionsTool.py @@ -1,112 +0,0 @@ -############################################################################## -# -# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. -# Copyright (c) 2009 Nexedi SARL and Contributors. All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## - -import logging - -logger = logging.getLogger(__name__) - -from Products.ERP5Type.Globals import InitializeClass -from AccessControl import ClassSecurityInfo -from Products.CMFCore.ActionsTool import ActionsTool -from Products.CMFCore.interfaces import IActionProvider -from Products.CMFCore.permissions import ManagePortal - -security = ClassSecurityInfo() - -def migrateNonProviders(portal_actions): - portal_actions_path = '/'.join(portal_actions.getPhysicalPath()) - portal = portal_actions.getPortalObject() - action_providers = list(portal_actions.action_providers) - for provider_name in portal_actions.listActionProviders(): - provider = getattr(portal, provider_name) - if ( getattr(provider, '_actions', ()) and - getattr(provider, 'listActionInfos', None) is None ): - logger.info('migrating actions from %r to %r', - portal_actions_path, '/'.join(provider.getPhysicalPath())) - portal_actions._actions += provider._actions - del provider._actions - if (getattr(provider, 'listActionInfos', None) is None and - getattr(provider, 'getActionListFor', None) is None and - not(IActionProvider.providedBy(provider))): - action_providers.remove(provider_name) - portal_actions.action_providers = tuple(action_providers) - -ActionsTool_listFilteredActionsFor = ActionsTool.listFilteredActionsFor - -def listFilteredActionsFor(self, object=None): - """ List all actions available to the user. - - This patch removes inclusion of actions from the object itself. - It was never used and now, it breaks objects inside Types Tool. - - It also checks for a new ERP5-only actions API (getActionListFor), but - this API should be moved to listActionInfos() of each tool so as not to - create duplicate code paths that are sources of bugs. - - Finally, this patch detects tools that are no longer action providers and - invokes the migration of their actions to portal_actions - """ - actions = [] - - # Include actions from specific tools. - for provider_name in self.listActionProviders(): - provider = getattr(self, provider_name) - if hasattr(provider, 'getActionListFor'): - from Products.ERP5Type.Utils import createExpressionContext - ec = createExpressionContext(object) - actions.extend(action.cook(ec) - for action in provider.getActionListFor(object) - if action.test(ec)) - elif IActionProvider.providedBy(provider): - actions.extend( provider.listActionInfos(object=object) ) - else: - # This should only be triggered once - # We're in 2.12 and we need to migrate objects that are no longer - # IActionProviders: - migrateNonProviders(self) - # Recompute from beginning - return self.listFilteredActionsFor(object=object) - - actions.sort(key=lambda x:x.get('priority', 0)) - # Reorganize the actions by category. - filtered_actions={'user':[], - 'folder':[], - 'object':[], - 'global':[], - 'workflow':[], - } - - for action in actions: - filtered_actions.setdefault(action['category'], []).append(action) - - return filtered_actions - -ActionsTool.listFilteredActionsFor = listFilteredActionsFor - - -def reorderActions(self, REQUEST=None): - """Reorder actions according to their priorities.""" - new_actions = self._cloneActions() - new_actions.sort(key=lambda x: x.getPriority()) - self._actions = tuple( new_actions ) - - if REQUEST is not None: - return self.manage_editActionsForm(REQUEST, - manage_tabs_message='Actions reordered.') - -security.declareProtected(ManagePortal, 'reorderActions') -ActionsTool.reorderActions = reorderActions - -ActionsTool.security = security -InitializeClass(ActionsTool) -- 2.30.9 From 6f0b9afffc44581f4079273e380cdb6e17d8760e Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Mon, 27 Apr 2015 10:24:24 +0300 Subject: [PATCH 3/9] BusinessTemplate: avoid remove portal_type/portal_actions/* when it installed in current businesstemplate as paths --- product/ERP5/Document/BusinessTemplate.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py index 1b36a3f4dcb..736c3887878 100644 --- a/product/ERP5/Document/BusinessTemplate.py +++ b/product/ERP5/Document/BusinessTemplate.py @@ -5246,6 +5246,25 @@ Business Template is a set of definitions, such as skins, portal types and categ for path in new_item._objects.keys(): modified_object_list.update({path : ['New', new_item.__class__.__name__[:-12]]}) + # XXX + # to avoid deletion of actions (should be done for any objects?) + # which have 2 presentation of link to them inside the bt + # it happens when object in the bt is installed and removed at same time + # analogue filter should be done when the object is moving from one bt to another + modified_object_list_filter = [] + for path, action in modified_object_list.iteritems(): + if action[0] == 'Removed' and action[1] == "Action": + if path.startswith('portal_types/portal_actions/'): + if path.replace('portal_types/portal_actions/', 'portal_actions/action_', 1) in modified_object_list: + modified_object_list_filter.append(path) + else: + fix_path, ob_id = posixpath.split(path) + fix_path = posixpath.join('portal_types', fix_path, 'action_' + ob_id) + if fix_path in modified_object_list: + modified_object_list_filter.append(path) + for path in modified_object_list_filter: + del modified_object_list[path] + if reinstall: self.portal_templates.manage_delObjects(ids=[INSTALLED_BT_FOR_DIFF]) -- 2.30.9 From a9be9c1857ac1da88b3c2413d4512625ec5b5c96 Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Thu, 14 May 2015 17:26:03 +0300 Subject: [PATCH 4/9] Into getRoleInformationList,getActionInformationList added tuple objectValues because CMFBTreeFolder.objectValues use LazyMap and object id is changed while objectValues run. This change should be included in 017d4d9a8d4ab3deac6efa8a94c0db1827b5882a --- product/ERP5Type/ActionProviderBase.py | 3 ++- product/ERP5Type/ERP5Type.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/product/ERP5Type/ActionProviderBase.py b/product/ERP5Type/ActionProviderBase.py index c35d980b053..02cc71c251a 100644 --- a/product/ERP5Type/ActionProviderBase.py +++ b/product/ERP5Type/ActionProviderBase.py @@ -60,7 +60,8 @@ class ActionProviderBase(object): 'getActionInformationList') def getActionInformationList(self): """Return all Action Information objects stored on this portal type""" - return self.objectValues(meta_type='ERP5 Action Information') + # tuple need because CMFBTreeFolder.objectValues use LazyMap and object id is changed while objectValues run + return tuple(self.objectValues(meta_type='ERP5 Action Information')) # # XXX CMF compatibility diff --git a/product/ERP5Type/ERP5Type.py b/product/ERP5Type/ERP5Type.py index 4cc0164f380..58b2afca9b4 100644 --- a/product/ERP5Type/ERP5Type.py +++ b/product/ERP5Type/ERP5Type.py @@ -157,7 +157,8 @@ class LocalRoleAssignorMixIn(object): 'getRoleInformationList') def getRoleInformationList(self): """Return all Role Information objects stored on this portal type""" - return self.objectValues(meta_type='ERP5 Role Information') + # tuple need because CMFBTreeFolder.objectValues use LazyMap and object id is changed while objectValues run + return tuple(self.objectValues(meta_type='ERP5 Role Information')) security.declareProtected(Permissions.ModifyPortalContent, 'updateRoleMapping') -- 2.30.9 From 6e48b97e139fa184670661e1c38ddc77ef35f8f8 Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Thu, 14 May 2015 22:09:53 +0300 Subject: [PATCH 5/9] gen_id_from_reference: fix log warning report --- product/ERP5Type/gen_id_from_reference.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/product/ERP5Type/gen_id_from_reference.py b/product/ERP5Type/gen_id_from_reference.py index 8c28f9791b0..7e698d63bbe 100644 --- a/product/ERP5Type/gen_id_from_reference.py +++ b/product/ERP5Type/gen_id_from_reference.py @@ -100,7 +100,10 @@ def GenerateIdFromReferenceMixin(prefix): except ActivityPendingError: parent = self.getParentValue() LOG("GenerateIdFromReferenceMixin", WARNING, "Skipping migration of %r in %r" - " %s, due to pending activities" % (old_id, parent.getId(), parent.getPortalType())) + " %s, due to pending activities" % (ob_id, parent.getId(), parent.getPortalType())) + self._v_idmigration = False + return ob_id + self._v_idmigration = False return new_id return ob_id -- 2.30.9 From 40218cda5de3d94a6765215800ba6359dac2d60d Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Thu, 14 May 2015 22:55:57 +0300 Subject: [PATCH 6/9] ActionTool: add clearGetActionListCache after migration and use cacheable getActionList --- product/ERP5Type/Tool/ActionsTool.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/product/ERP5Type/Tool/ActionsTool.py b/product/ERP5Type/Tool/ActionsTool.py index a3c67f62ae1..c7ad0564ff2 100644 --- a/product/ERP5Type/Tool/ActionsTool.py +++ b/product/ERP5Type/Tool/ActionsTool.py @@ -67,8 +67,10 @@ class ActionsTool(BaseTool, ActionProviderBase, CMFCore_ActionsTool): getattr(provider, 'listActionInfos', None) is None ): logger.info('migrating actions from %r to %r', portal_actions_path, '/'.join(provider.getPhysicalPath())) - for old_action in provider._actions: - self._importOldAction(old_action) + if provider._actions: + for old_action in provider._actions: + self._importOldAction(old_action) + self.clearGetActionListCache() del provider._actions if (getattr(provider, 'listActionInfos', None) is None and getattr(provider, 'getActionListFor', None) is None and @@ -76,9 +78,10 @@ class ActionsTool(BaseTool, ActionProviderBase, CMFCore_ActionsTool): action_providers.remove(provider_name) self.action_providers = tuple(action_providers) - security.declarePrivate('getActionListFor') - def getActionListFor(self, ob=None): - """Return all actions applicable to the object""" + security.declareProtected(Permissions.AccessContentsInformation, + 'getActionInformationList') + def getActionInformationList(self): + """Return all Action Information objects stored on this portal type""" old_actions = self._actions or () if old_actions: LOG('OldActionsTool', WARNING, "Converting portal_actions...") @@ -87,8 +90,15 @@ class ActionsTool(BaseTool, ActionProviderBase, CMFCore_ActionsTool): self._importOldAction(action_info) LOG('OldActionsTool', WARNING, "... portal_actions converted.") self._actions = () + self.clearGetActionListCache() + + return ActionProviderBase.getActionInformationList(self) + + security.declarePrivate('getActionListFor') + def getActionListFor(self, ob=None): + """Return all actions applicable to the object""" if ob is not None: - return (action.getCacheableAction() for action in self.objectValues()) + return self.getActionList() return () def listFilteredActionsFor(self, object=None): -- 2.30.9 From aacc7bc1d8ca831e1526b624efc669a71ea54ad9 Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Wed, 20 May 2015 11:36:47 +0300 Subject: [PATCH 7/9] BusinessTemplate: fix problem of not installment bt's actions whose containers are not IActionProvider. This problem arised as result of my convert portal_action to erp5's action tool. --- product/ERP5/Document/BusinessTemplate.py | 26 ++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py index 736c3887878..32612a510d0 100644 --- a/product/ERP5/Document/BusinessTemplate.py +++ b/product/ERP5/Document/BusinessTemplate.py @@ -83,6 +83,7 @@ from warnings import warn from lxml.etree import parse from xml.sax.saxutils import escape from Products.CMFCore.Expression import Expression +from Products.CMFCore.interfaces import IActionProvider from urllib import quote, unquote from difflib import unified_diff import posixpath @@ -3186,7 +3187,6 @@ class ActionTemplateItem(ObjectTemplateItem): return obj._exportOldAction(action) def _getPortalToolActionCopy(self, obj, context, value): - from Products.CMFCore.interfaces import IActionProvider if not IActionProvider.providedBy(obj): # look for the action in portal_actions, instead of the original object LOG('Products.ERP5.Document.BusinessTemplate', WARNING, @@ -3253,7 +3253,19 @@ class ActionTemplateItem(ObjectTemplateItem): container = p.unrestrictedTraverse(path) if interfaces.ITypeProvider.providedBy(aq_parent(aq_inner(container)))\ - or IActionsTool.providedBy(container): + or IActionsTool.providedBy(container)\ + or not IActionProvider.providedBy(container): + + if not IActionProvider.providedBy(container): + # some tools stopped being ActionProviders in CMF 2.x. Drop the + # action into portal_actions. + LOG('Products.ERP5.Document.BusinessTemplate', WARNING, + 'Redirected action import', + 'Attempted to store action %r in %r which is no longer an ' + 'IActionProvider. Storing action on portal_actions instead' % + (id, path)) + path = 'portal_actions' + # XXX future BT should use 'reference' instead of 'id' reference = getattr(obj, 'reference', None) or obj.id portal_type_dict.setdefault(path, {})[reference] = obj @@ -3261,16 +3273,6 @@ class ActionTemplateItem(ObjectTemplateItem): # Following code is for actions outside Types Tool. # It will be removed when they are also converted to ERP5 actions. - from Products.CMFCore.interfaces import IActionProvider - if not IActionProvider.providedBy(container): - # some tools stopped being ActionProviders in CMF 2.x. Drop the - # action into portal_actions. - LOG('Products.ERP5.Document.BusinessTemplate', WARNING, - 'Redirected action import', - 'Attempted to store action %r in %r which is no longer an ' - 'IActionProvider. Storing action on portal_actions instead' % - (id, path)) - container = p.portal_actions obj, action = container, obj action_list = obj.listActions() for index in range(len(action_list)): -- 2.30.9 From 854d4c21b609c82a66c390054156122483408ac2 Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Sat, 18 Jul 2015 11:34:24 +0300 Subject: [PATCH 8/9] ActionTool: add clearGetActionListCache after migration and use cacheable getActionList --- product/ERP5Type/Core/ActionInformation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/product/ERP5Type/Core/ActionInformation.py b/product/ERP5Type/Core/ActionInformation.py index 128e246ac85..480a8e3ea45 100644 --- a/product/ERP5Type/Core/ActionInformation.py +++ b/product/ERP5Type/Core/ActionInformation.py @@ -144,7 +144,9 @@ class ActionInformation(GenerateIdFromReferenceMixin('action'), XMLObject): icon=self.getIconText(), action=self.getActionText(), condition=self.getConditionText(), - permission_list=self.getActionPermissionList()) + permission_list=self.getActionPermissionList(), + visible=self.isVisible(), + ) class CacheableAction(object): -- 2.30.9 From c698b09a5e4e597c52f391eae8fe15bd4654feff Mon Sep 17 00:00:00 2001 From: Boris Kocherov Date: Sat, 18 Jul 2015 11:38:45 +0300 Subject: [PATCH 9/9] BusinessTemplate: fix problem of not installment bt's actions whose containers are not IActionProvider. This problem arisen as result of my convert portal_action to erp5's action tool. --- product/ERP5/tests/testBusinessTemplate.py | 39 +++++++++++++--------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/product/ERP5/tests/testBusinessTemplate.py b/product/ERP5/tests/testBusinessTemplate.py index fc3af22a6ba..e01583dc337 100644 --- a/product/ERP5/tests/testBusinessTemplate.py +++ b/product/ERP5/tests/testBusinessTemplate.py @@ -536,6 +536,13 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): if x.getReference() == action_id] object_type._delObject(action_id) + def stepRemoveFirstActionFromPath(self, sequence=None, **kw): + bt = sequence.get('current_bt', None) + self.assertTrue(bt is not None) + path_list = list(bt.getTemplatePathList()) + path_list.remove('portal_types/Geek Object/action_become_geek') + bt.setTemplatePathList(path_list) + def stepCheckPortalTypeExists(self, sequence=None, **kw): """ Check presence of portal type @@ -1287,7 +1294,9 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): bc_id = sequence.get('bc_id') bt = sequence.get('current_bt') path = 'portal_categories/'+bc_id+'/**' - bt.edit(template_path_list=[path]) + path_list = list(bt.getTemplatePathList()) + path_list.append(path) + bt.edit(template_path_list=path_list) def stepCheckSubCategoriesExists(self, sequence=None, **kw): bc_id = sequence.get('bc_id') @@ -2579,7 +2588,7 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): def stepCheckBeforeReinstall(self, sequence=None, **kw): import_bt = sequence.get('current_bt') diff_list = import_bt.BusinessTemplate_getModifiedObject() - self.assertTrue('portal_types/Geek Object/become_geek' + self.assertTrue('portal_types/Geek Object/action_become_geek' in [line.object_id for line in diff_list]) def stepInstallCurrentBusinessTemplate(self, sequence=None, **kw): @@ -5923,6 +5932,7 @@ class TestBusinessTemplate(BusinessTemplateMixin): InstallCurrentBusinessTemplate Tic \ Tic \ RemoveFirstAction \ + RemoveFirstActionFromPath \ CheckBeforeReinstall \ ReinstallBusinessTemplate Tic \ \ @@ -6572,20 +6582,19 @@ class TestBusinessTemplate(BusinessTemplateMixin): def test_global_action(self): # Tests that global actions are properly exported and reimported - self.portal.portal_actions.addAction( - id='test_global_action', - name='Test Global Action', - action='', - condition='', - permission='', - category='object_view') - action_idx = len(self.portal.portal_actions._actions) + portal_actions = self.portal.portal_actions + portal_actions.newContent( + portal_type='Action Information', + reference='test_global_action', + title='Test Global Action', + action_type='object_view') + action_id = 'action_test_global_action' bt = self.portal.portal_templates.newContent( portal_type='Business Template', title='test_bt_%s' % self.id(), - template_action_path_list=( - 'portal_actions | test_global_action',),) + template_path_list=( + 'portal_actions/action_test_global_action',),) self.tic() bt.build() self.tic() @@ -6597,14 +6606,14 @@ class TestBusinessTemplate(BusinessTemplateMixin): # tool self.assertEqual(['portal_actions'], [os.path.basename(f) for f in - glob.glob('%s/ActionTemplateItem/portal_types/*' % (export_dir, ))]) + glob.glob('%s/PathTemplateItem/*' % (export_dir, ))]) new_bt = self.portal.portal_templates.download( url='file:/%s' % export_dir) finally: shutil.rmtree(export_dir) # manually uninstall the action - self.portal.portal_actions.deleteActions(selections=[action_idx]) + portal_actions._delObject(action_id) self.tic() # install the business template and make sure the action is properly @@ -6612,7 +6621,7 @@ class TestBusinessTemplate(BusinessTemplateMixin): new_bt.install() self.tic() self.assertNotEquals(None, - self.portal.portal_actions.getActionInfo('object_view/test_global_action')) + portal_actions._getOb(action_id, None)) def test_indexation_of_updated_path_item(self): """Tests indexation on updated paths item. -- 2.30.9