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
self._catalog_local_role_key_item = \
self._catalog_security_uid_column_item = \
# The following properties have been introduced later on. See
# PropertySheetTool to handle smoothly instances not upgraded yet.
self._catalog_security_uid_column_item = \
self._interface_item = \
self._interface_item = \
self._mixin_item = \
self._mixin_item = \
except AttributeError:
# be backwards compatible with old zope instances which
# do not contain recent version of erp5_property_sheets
security.declareProtected(Permissions.ManagePortal, 'build')
def build(self, no_action=0, update_revision=True):
......@@ -2017,7 +2017,7 @@ class ERP5Generator(PortalGenerator):
return p
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)
from Products.ERP5.Document.BusinessTemplate import quote
traverse = context.unrestrictedTraverse
......@@ -2025,16 +2025,22 @@ class ERP5Generator(PortalGenerator):
prefix_len = len(os.path.join(top, ''))
for root, dirs, files in os.walk(top):
container_path = root[prefix_len:]
load = traverse(container_path)._importObjectFromFile
container_obj = traverse(container_path)
load = container_obj._importObjectFromFile
if container_path:
id_set = {x[:-4] for x in files if x[-4:] == '.xml'}
id_set = {quote(x) for x in content_id_list
if not context.hasObject(x)}
id_set = set()
for content_path in content_path_list:
except (KeyError, AttributeError):
id_set.add(quote(content_path.split('/', 1)[0]))
dirs[:] = id_set.intersection(dirs)
for file in id_set:
load(os.path.join(root, file + '.xml'),
verify=False, set_owner=False, suppress_events=True)
for id_ in id_set:
if not container_obj.hasObject(id_):
load(os.path.join(root, id_ + '.xml'),
verify=False, set_owner=False, suppress_events=True)
def bootstrap_allow_type(types_tool, portal_type):
......@@ -56,13 +56,28 @@ class PropertySheetTool(BaseTool):
security = ClassSecurityInfo()
# 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 = (
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):
bt_name = 'erp5_property_sheets'
from Products.ERP5.ERP5Site import ERP5Generator
ERP5Generator.bootstrap(self, bt_name, 'PropertySheetTemplateItem', (
content_path_list = [
......@@ -72,8 +87,12 @@ class PropertySheetTool(BaseTool):
# the following ones are required to upgrade an existing site
'BusinessTemplate/' + bt_property
for bt_property in self._bootstrap_business_template_property_tuple])
ERP5Generator.bootstrap(self, bt_name, 'PropertySheetTemplateItem',
def install():
from ZPublisher.BaseRequest import RequestContainer
from Products.ERP5Type.Globals import get_request
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment