Commit d9627917 authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: Properly handle addition of template_* properties in...

ZODB Components: Properly handle addition of template_* properties in BusinessTemplate PropertySheet.

On the plus side, this avoids an ugly 'except AttributeError: pass' which does
not work anyway with the scenario below.

Assuming the following:
  * template_XXX Property (accessor: getTemplateXXX) recently added to BusinessTemplate PropertySheet.
  * erp5_YYY sets template_A Property (erp5_YYY/bt/template_XXX.xml).
  This commit handles the following:
    1. Stop instance with old ERP5 without template_XXX.
    2. Update erp5.git.
    3. Start instance.
    4. Upgrade erp5_property_sheets and erp5_YYY bt5s in *one* transaction from portal_templates UI.
    => When upgrading erp5_YYY, BusinessTemplate.importFile() imports erp5_YYY/bt/*.xml where the
       list of files is based on BusinessTemplate class propertyMap(), but at this point accessors
       have not been re-generated yet, thus template_XXX is not returned by propertyMap() and
       erp5_YYY/bt/template_XXX.xml is not imported.
       => portal_templates/erp5_YYY new BT does not have template_XXX property set at all.
parent 0a66e514
...@@ -5238,18 +5238,15 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -5238,18 +5238,15 @@ Business Template is a set of definitions, such as skins, portal types and categ
self._catalog_local_role_key_item = \ self._catalog_local_role_key_item = \
CatalogLocalRoleKeyTemplateItem( CatalogLocalRoleKeyTemplateItem(
self.getTemplateCatalogLocalRoleKeyList()) self.getTemplateCatalogLocalRoleKeyList())
try: # The following properties have been introduced later on. See
self._catalog_security_uid_column_item = \ # PropertySheetTool to handle smoothly instances not upgraded yet.
self._catalog_security_uid_column_item = \
CatalogSecurityUidColumnTemplateItem( CatalogSecurityUidColumnTemplateItem(
self.getTemplateCatalogSecurityUidColumnList()) self.getTemplateCatalogSecurityUidColumnList())
self._interface_item = \ self._interface_item = \
InterfaceTemplateItem(self.getTemplateInterfaceIdList()) InterfaceTemplateItem(self.getTemplateInterfaceIdList())
self._mixin_item = \ self._mixin_item = \
MixinTemplateItem(self.getTemplateMixinIdList()) MixinTemplateItem(self.getTemplateMixinIdList())
except AttributeError:
# be backwards compatible with old zope instances which
# do not contain recent version of erp5_property_sheets
pass
security.declareProtected(Permissions.ManagePortal, 'build') security.declareProtected(Permissions.ManagePortal, 'build')
def build(self, no_action=0, update_revision=True): def build(self, no_action=0, update_revision=True):
......
...@@ -2017,7 +2017,7 @@ class ERP5Generator(PortalGenerator): ...@@ -2017,7 +2017,7 @@ class ERP5Generator(PortalGenerator):
return p return p
@classmethod @classmethod
def bootstrap(cls, context, bt_name, item_name, content_id_list): def bootstrap(cls, context, bt_name, item_name, content_path_list):
bt_path = getBootstrapBusinessTemplateUrl(bt_name) bt_path = getBootstrapBusinessTemplateUrl(bt_name)
from Products.ERP5.Document.BusinessTemplate import quote from Products.ERP5.Document.BusinessTemplate import quote
traverse = context.unrestrictedTraverse traverse = context.unrestrictedTraverse
...@@ -2025,16 +2025,22 @@ class ERP5Generator(PortalGenerator): ...@@ -2025,16 +2025,22 @@ class ERP5Generator(PortalGenerator):
prefix_len = len(os.path.join(top, '')) prefix_len = len(os.path.join(top, ''))
for root, dirs, files in os.walk(top): for root, dirs, files in os.walk(top):
container_path = root[prefix_len:] container_path = root[prefix_len:]
load = traverse(container_path)._importObjectFromFile container_obj = traverse(container_path)
load = container_obj._importObjectFromFile
if container_path: if container_path:
id_set = {x[:-4] for x in files if x[-4:] == '.xml'} id_set = {x[:-4] for x in files if x[-4:] == '.xml'}
else: else:
id_set = {quote(x) for x in content_id_list id_set = set()
if not context.hasObject(x)} for content_path in content_path_list:
try:
traverse(content_path)
except (KeyError, AttributeError):
id_set.add(quote(content_path.split('/', 1)[0]))
dirs[:] = id_set.intersection(dirs) dirs[:] = id_set.intersection(dirs)
for file in id_set: for id_ in id_set:
load(os.path.join(root, file + '.xml'), if not container_obj.hasObject(id_):
verify=False, set_owner=False, suppress_events=True) load(os.path.join(root, id_ + '.xml'),
verify=False, set_owner=False, suppress_events=True)
@staticmethod @staticmethod
def bootstrap_allow_type(types_tool, portal_type): def bootstrap_allow_type(types_tool, portal_type):
......
...@@ -56,13 +56,28 @@ class PropertySheetTool(BaseTool): ...@@ -56,13 +56,28 @@ class PropertySheetTool(BaseTool):
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# Business Template properties introduced later on have to be there as
# _importFile a bt will look at propertyMap() to set properties
_bootstrap_business_template_property_tuple = (
'template_catalog_security_uid_column_property',
'template_interface_id_property',
'template_mixin_id_property')
def _isBootstrapRequired(self): def _isBootstrapRequired(self):
return not self.has_key('BaseType') if not self.has_key('BaseType'):
return True
bt_has_key = self.BusinessTemplate.has_key
for bt_property in self._bootstrap_business_template_property_tuple:
if not bt_has_key(bt_property):
return True
return False
def _bootstrap(self): def _bootstrap(self):
bt_name = 'erp5_property_sheets' bt_name = 'erp5_property_sheets'
from Products.ERP5.ERP5Site import ERP5Generator from Products.ERP5.ERP5Site import ERP5Generator
ERP5Generator.bootstrap(self, bt_name, 'PropertySheetTemplateItem', ( content_path_list = [
'BaseType', 'BaseType',
'BusinessTemplate', 'BusinessTemplate',
'Folder', 'Folder',
...@@ -72,8 +87,12 @@ class PropertySheetTool(BaseTool): ...@@ -72,8 +87,12 @@ class PropertySheetTool(BaseTool):
# the following ones are required to upgrade an existing site # the following ones are required to upgrade an existing site
'Reference', 'Reference',
'BaseCategory', 'BaseCategory',
'SQLIdGenerator', 'SQLIdGenerator']
)) content_path_list.extend([
'BusinessTemplate/' + bt_property
for bt_property in self._bootstrap_business_template_property_tuple])
ERP5Generator.bootstrap(self, bt_name, 'PropertySheetTemplateItem',
content_path_list)
def install(): def install():
from ZPublisher.BaseRequest import RequestContainer from ZPublisher.BaseRequest import RequestContainer
from Products.ERP5Type.Globals import get_request from Products.ERP5Type.Globals import get_request
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment