Commit d40e3eea authored by Nicolas Wavrant's avatar Nicolas Wavrant Committed by Ayush Tiwari

BusinessTemplate: any single property of any object can be save in a bt5

It is useful to save some customizations, preferences, or eve additions for test business templates
This feature is managed by a new class: ObjectPropertyTemplateItem
parent 258fcc65
......@@ -4928,6 +4928,80 @@ class LocalRolesTemplateItem(BaseTemplateItem):
delattr(obj, '__ac_local_roles_group_id_dict__')
obj.reindexObject()
class ObjectPropertyTemplateItem(BaseTemplateItem):
xml_tag = "object_property_list"
def build(self, context, **kw):
p = context.getPortalObject()
for key in self._archive:
relative_url, property_name = key.split(' | ')
property_value = p.unrestrictedTraverse(relative_url) \
.getProperty(property_name)
self._objects.setdefault(relative_url, {})[property_name] = property_value
def generateXml(self, path=None):
xml_data = '<%s>' % self.xml_tag
for relative_url in self._objects:
xml_data += '\n <object relative_url="%s">' % relative_url
for property_name, property_value in self._objects[relative_url].iteritems():
xml_data += '\n <property name="%s">' % property_name.replace('_list', '')
if property_name.endswith('_list'):
for value in property_value:
xml_data += '\n <item>%s</item>' % value
else:
xml_data += '\n <item>%s</item>' % property_value
xml_data += '\n </property>'
xml_data += '\n </object>'
xml_data += '\n</%s>' % self.xml_tag
return xml_data
def export(self, context, bta, **kw):
path = self.__class__.__name__
if self._objects.keys():
xml_data = self.generateXml()
bta.addObject(xml_data, name=self.xml_tag, path=path)
def _importFile(self, file_name, file):
if not file_name.endswith('.xml'):
LOG('Business Template', 0, 'Skipping file "%s"' % (file_name, ))
return
xml = parse(file)
object_list = xml.findall('object')
for obj in object_list:
for obj_property in obj.findall('property'):
item_list = []
for item in obj_property.findall('item'):
item_list.append(item.text)
property_name = obj_property.get('name') + ('' if len(item_list) <= 1 else '_list')
self._objects[obj.get('relative_url')] = {property_name: item_list}
def preinstall(self, context, installed_item, **kw):
modified_object_list = {}
for relative_url in self._objects:
new_object = self._objects[relative_url]
try:
old_object = installed_item._objects[relative_url]
except KeyError:
modified_object_list.update({relative_url : ['New', self.__class__.__name__[:-12]]})
else:
modified_object_list.update({relative_url : ['Modified', self.__class__.__name__[:-12]]})
return modified_object_list
def install(self, context, trashbin, **kw):
portal = context.getPortalObject()
for relative_url in self._objects:
obj = portal.unrestrictedTraverse(relative_url)
for property_name, property_value in self._objects[relative_url].iteritems():
obj.setProperty(property_name, property_value)
def uninstall(self, context, **kw):
portal = context.getPortalObject()
for relative_url in self._objects:
obj = portal.unrestrictedTraverse(relative_url)
for property_name in self._objects[relative_url]:
obj.setProperty(property_name, None)
class bt(dict):
"""Fake 'bt' item to read bt/* files through BusinessTemplateArchive"""
......@@ -5163,6 +5237,8 @@ Business Template is a set of definitions, such as skins, portal types and categ
self._catalog_local_role_key_item = \
CatalogLocalRoleKeyTemplateItem(
self.getTemplateCatalogLocalRoleKeyList())
self._object_property_item = \
ObjectPropertyTemplateItem(self.getTemplateObjectPropertyList())
try:
self._catalog_security_uid_column_item = \
CatalogSecurityUidColumnTemplateItem(
......@@ -5944,6 +6020,7 @@ Business Template is a set of definitions, such as skins, portal types and categ
'CatalogRoleKey' : '_catalog_role_key_item',
'CatalogLocalRoleKey' : '_catalog_local_role_key_item',
'CatalogSecurityUidColumn' : '_catalog_security_uid_column_item',
'ObjectProperty': '_object_property_item',
}
object_id = REQUEST.object_id
......@@ -6013,7 +6090,8 @@ Business Template is a set of definitions, such as skins, portal types and categ
'_portal_type_roles_item',
'_portal_type_base_category_item',
'_local_roles_item',
'_portal_type_workflow_chain_item',]
'_portal_type_workflow_chain_item',
'_object_property_item',]
# Text objects (no need to export them into XML)
# XXX Bad naming
......
......@@ -96,6 +96,7 @@ item_name_list = (
'catalog_role_key',
'catalog_local_role_key',
'catalog_security_uid_column',
'object_property',
)
item_set = set(('CatalogDateTimeKey' if x == 'catalog_datetime_key' else
......
......@@ -83,6 +83,7 @@
<string>my_template_constraint_id_list</string>
<string>my_template_local_role_list</string>
<string>my_template_portal_type_role_list</string>
<string>my_template_object_property_list</string>
</list>
</value>
</item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="LinesField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_template_object_property_list</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>line_too_long</string> </key>
<value> <string>A line was too long.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>You entered too many characters.</string> </value>
</item>
<item>
<key> <string>too_many_lines</string> </key>
<value> <string>You entered too many lines.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Object Properties</string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>view_separator</string> </key>
<value> <string encoding="cdata"><![CDATA[
<br />\n
]]></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>40</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/lines</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>A list of base categories for portal types</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_object_property_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: ()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -7231,6 +7231,64 @@ class TestBusinessTemplate(BusinessTemplateMixin):
self.assertEqual(True, method("aa/bb"))
self.assertEqual(True, method("aa/bb/cc"))
def stepSetPropertyOnModule(self, sequence=None, **kw):
module_id = sequence.get('module_id')
module = self.getPortalObject()[module_id]
for name, value in self.object_property_dict.iteritems():
module.setProperty(name, value)
def stepAddModulePropertyToBusinessTemplate(self, sequence=None, **kw):
module_id = sequence.get('module_id')
bt_object_property_list = []
for property_name, _ in self.object_property_dict.iteritems():
bt_object_property_list.append("%s | %s" % (module_id, property_name))
bt = sequence.get('export_bt')
bt.edit(template_object_property_list=bt_object_property_list)
def stepCheckModuleProperty(self, sequence=None, **kw):
module_id = sequence.get('module_id')
module = self.getPortalObject()[module_id]
for name, value in self.object_property_dict.iteritems():
self.assertEqual(module.getProperty(name), value)
def stepCheckModulePropertyIsNone(self, sequence=None, **kw):
module_id = sequence.get('module_id')
module = self.getPortalObject()[module_id]
for property_name, _ in self.object_property_dict.iteritems():
self.assertEqual(module.getProperty(property_name), None)
test_object_property_string = """
CreatePortalType
CreateModuleAndObjects
stepSetPropertyOnModule
CheckModuleProperty
CreateNewBusinessTemplate
UseExportBusinessTemplate
AddModulePropertyToBusinessTemplate
BuildBusinessTemplate
CheckBuiltBuildingState
SaveBusinessTemplate
RemoveModule
CreateModuleAndObjects
CheckModulePropertyIsNone
UseExportBusinessTemplate
stepInstallCurrentBusinessTemplate
CheckModuleProperty
"""
def test_ExportAndImportObjectProperty(self):
sequence = Sequence()
self.object_property_dict = {'business_application': 'base'}
sequence.setSequenceString(self.test_object_property_string)
sequence.play(self)
# Same test as before, but with a category_list property
def test_ExportAndImportObjectPropertyList(self):
sequence = Sequence()
self.object_property_dict = {'business_application_list': ('base', 'extended')}
sequence.setSequenceString(self.test_object_property_string)
sequence.play(self)
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class TestDocumentTemplateItem(BusinessTemplateMixin):
......
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