Commit 4cf40e3f authored by Arnaud Fontaine's avatar Arnaud Fontaine

Add Business Template action to import Document and Extensions automatically...

Add Business Template action to import Document and Extensions automatically after giving the version.

Migration is now performed at Business Template level as it makes more
sense rather than on Component Tool which would require specifying the
target Business Template to update Document Template Item and
Extension Template Item.
parent b53f29a3
...@@ -5741,6 +5741,61 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -5741,6 +5741,61 @@ Business Template is a set of definitions, such as skins, portal types and categ
setattr(self, 'template_portal_type_base_category', ()) setattr(self, 'template_portal_type_base_category', ())
return return
security.declareProtected(Permissions.ModifyPortalContent,
'migrateAllComponentFromFilesystem')
def migrateAllComponentFromFilesystem(self,
version_priority,
erase_existing=False,
**kw):
component_tool = self.getPortalObject().portal_components
failed_import_dict = {}
# XXX-arnau: dirty because of copy/paste but will be refactor
# later with Products anyway...
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
document_id_list = self.getTemplateDocumentIdList()
for i, reference in enumerate(document_id_list):
try:
obj = DocumentComponent.importFromFilesystem(component_tool,
reference,
version_priority,
erase_existing)
except Exception, e:
failed_import_dict[reference] = str(e)
else:
document_id_list[i] = obj.getId()
self.setTemplateDocumentIdList(document_id_list)
from Products.ERP5Type.Core.ExtensionComponent import ExtensionComponent
extension_id_list = self.getTemplateExtensionIdList()
for i, reference in enumerate(extension_id_list):
try:
obj = ExtensionComponent.importFromFilesystem(component_tool,
reference,
version_priority,
erase_existing)
except Exception, e:
failed_import_dict[reference] = str(e)
else:
extension_id_list[i] = obj.getId()
self.setTemplateExtensionIdList(extension_id_list)
if failed_import_dict:
failed_import_formatted_list = []
for name, error in failed_import_dict.iteritems():
failed_import_formatted_list.append("%s (%s)" % (name, error))
message = "The following component could not be imported: %s" % \
', '.join(failed_import_formatted_list)
else:
message = "All components were successfully imported " \
"from filesystem to ZODB."
return self.Base_redirect('view',
keep_items={'portal_status_message': message})
# Block acquisition on all _item_name_list properties by setting # Block acquisition on all _item_name_list properties by setting
# a default class value to None # a default class value to None
for key in BusinessTemplate._item_name_list: for key in BusinessTemplate._item_name_list:
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>migrate_component_from_filesystem</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Add portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Migrate Components From Filesystem</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/BusinessTemplate_viewMigrateAllComponentFromFilesystemDialog</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>template_document_id_list = context.getTemplateDocumentIdList()\n
template_extension_id_list = context.getTemplateExtensionIdList()\n
if not (template_document_id_list or template_extension_id_list):\n
return []\n
\n
migrated_component_id_list = template_document_id_list + template_extension_id_list\n
portal = context.getPortalObject()\n
component_tool = portal.portal_components\n
\n
from Products.ERP5Type.Document import newTempBase\n
def addLineListByType(id_list, destination_portal_type, line_list):\n
for component_id in id_list:\n
if getattr(component_tool, component_id, None) is not None:\n
continue\n
\n
line = newTempBase(context,\n
\'tmp_migrate_%s_%s\' % (destination_portal_type, component_id),\n
uid=component_id,\n
name=component_id,\n
destination_portal_type=destination_portal_type)\n
\n
line_list.append(line)\n
\n
line_list = []\n
addLineListByType(template_document_id_list, \'Document Component\', line_list)\n
addLineListByType(template_extension_id_list, \'Extension Component\', line_list)\n
return line_list\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>*args, **kwargs</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>BusinessTemplate_getComponentMigratedFromFilesystemList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5Form" module="Products.ERP5Form.Form"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>migrateAllComponentFromFilesystem</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>listbox</string>
</list>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>my_version_priority</string>
<string>my_erase_existing</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>BusinessTemplate_viewMigrateAllComponentFromFilesystemDialog</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>BusinessTemplate_viewMigrateAllComponentFromFilesystem</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_dialog</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Migrate Components from filesystem to ZODB</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_erase_existing</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>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_checkbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Erase Existing</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>first_item</string>
<string>items</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_version_priority</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>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_list_field</string> </value>
</item>
<item>
<key> <string>first_item</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Version</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: [(v, v) for v in here.getPortalObject().getVersionPriority()]</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
2012-02-20 arnaud.fontaine
* Add Business Template action to import Document and Extensions automatically after giving the version.
2012-02-14 arnaud.fontaine 2012-02-14 arnaud.fontaine
* Add component_interaction_workflow to Component Tool. * Add component_interaction_workflow to Component Tool.
......
41002 41003
\ No newline at end of file \ No newline at end of file
...@@ -29,6 +29,7 @@ Business Template | export ...@@ -29,6 +29,7 @@ Business Template | export
Business Template | get_portal_type_properties Business Template | get_portal_type_properties
Business Template | guess_portal_types Business Template | guess_portal_types
Business Template | jump_trash_bin Business Template | jump_trash_bin
Business Template | migrate_component_from_filesystem
Business Template | save Business Template | save
Business Template | unittest_run Business Template | unittest_run
Business Template | view Business Template | view
......
...@@ -7063,7 +7063,8 @@ class TestDocumentTemplateItem(BusinessTemplateMixin): ...@@ -7063,7 +7063,8 @@ class TestDocumentTemplateItem(BusinessTemplateMixin):
document_object = self.importFromFilesystem( document_object = self.importFromFilesystem(
component_tool, component_tool,
os.path.join(sequence['document_path'])) sequence['document_title'],
'erp5')
sequence.edit(document_id=document_object.getId()) sequence.edit(document_id=document_object.getId())
......
...@@ -215,30 +215,6 @@ class Component(Base): ...@@ -215,30 +215,6 @@ class Component(Base):
def _getFilesystemPath(): def _getFilesystemPath():
raise NotImplementedError raise NotImplementedError
security.declareProtected(Permissions.ModifyPortalContent,
'importAllFromFilesystem')
@classmethod
def importAllFromFilesystem(cls, context, erase_existing=False):
"""
Try to import all Components and returns error as a dict if any
"""
import os.path
path_pattern = "%s%s*.py" % (cls._getFilesystemPath(), os.path.sep)
LOG("ERP5Type.Core.Component", INFO, "Importing from %s" % path_pattern)
import glob
failed_import_dict = {}
for path in glob.iglob(path_pattern):
try:
cls.importFromFilesystem(context, path, erase_existing)
except Exception, e:
failed_import_dict[path] = str(e)
else:
LOG("ERP5Type.Core.Component", INFO, "Imported %s" % path)
return failed_import_dict
@staticmethod @staticmethod
def _getDynamicModuleNamespace(): def _getDynamicModuleNamespace():
raise NotImplementedError raise NotImplementedError
...@@ -246,22 +222,25 @@ class Component(Base): ...@@ -246,22 +222,25 @@ class Component(Base):
security.declareProtected(Permissions.ModifyPortalContent, security.declareProtected(Permissions.ModifyPortalContent,
'importFromFilesystem') 'importFromFilesystem')
@classmethod @classmethod
def importFromFilesystem(cls, context, path, erase_existing=False): def importFromFilesystem(cls, context, reference, version,
erase_existing=False):
""" """
Import a Component from the given path into ZODB after checking that the Import a Component from the given path into ZODB after checking that the
source code is valid source code is valid
""" """
import os.path object_id = '%s.%s.%s' % (cls._getDynamicModuleNamespace(), version,
class_name = os.path.basename(path).replace('.py', '') reference)
id = '%s.%s' % (cls._getDynamicModuleNamespace(), class_name)
# XXX-arnau: not efficient at all obj = context._getOb(object_id, None)
if id in context: if obj is not None:
if not erase_existing: if not erase_existing:
return obj.validate()
return obj
context.deleteContent(id) context.deleteContent(object_id)
import os.path
path = os.path.join(cls._getFilesystemPath(), reference + '.py')
with open(path) as f: with open(path) as f:
source_code = f.read() source_code = f.read()
...@@ -269,8 +248,9 @@ class Component(Base): ...@@ -269,8 +248,9 @@ class Component(Base):
namespace_dict = {} namespace_dict = {}
exec source_code in namespace_dict exec source_code in namespace_dict
new_component = context.newContent(id=id, new_component = context.newContent(id=object_id,
reference=class_name, reference=reference,
version=version,
text_content=source_code, text_content=source_code,
portal_type=cls.portal_type) portal_type=cls.portal_type)
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
############################################################################## ##############################################################################
# #
# Copyright (c) 2011 Nexedi SA and Contributors. All Rights Reserved. # Copyright (c) 2011-2012 Nexedi SA and Contributors. All Rights Reserved.
# Jean-Paul Smets <jp@nexedi.com> # Jean-Paul Smets <jp@nexedi.com>
# Arnaud Fontaine <arnaud.fontaine@nexedi.com>
# #
# WARNING: This program as such is intended to be used by professional # WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential # programmers who take the whole responsability of assessing all potential
...@@ -43,9 +44,9 @@ from zLOG import LOG, INFO, WARNING ...@@ -43,9 +44,9 @@ from zLOG import LOG, INFO, WARNING
_last_sync = -1 _last_sync = -1
class ComponentTool(BaseTool): class ComponentTool(BaseTool):
""" """
This tool provides methods to load the the different types This tool provides methods to load the the different types of
of components of the ERP5 framework: Document classes, interfaces, components of the ERP5 framework: Document classes, interfaces,
mixin classes, fields, accessors, etc. mixin classes, fields, accessors, etc.
""" """
id = "portal_components" id = "portal_components"
meta_type = "ERP5 Component Tool" meta_type = "ERP5 Component Tool"
...@@ -129,43 +130,3 @@ class ComponentTool(BaseTool): ...@@ -129,43 +130,3 @@ class ComponentTool(BaseTool):
if key not in tv: if key not in tv:
tv[key] = None tv[key] = None
transaction.get().addBeforeCommitHook(self.reset) transaction.get().addBeforeCommitHook(self.reset)
security.declareProtected(Permissions.ModifyPortalContent,
'createAllComponentFromFilesystem')
def createAllComponentFromFilesystem(self, erase_existing=False,
REQUEST=None):
"""
XXX-arnau: only bt5 Extensions and Documents for now
"""
portal = self.getPortalObject()
import erp5.portal_type
type_tool = portal.portal_types
failed_import_dict = {}
for content_portal_type in getattr(type_tool,
self.portal_type).getTypeAllowedContentTypeList():
try:
failed_import_dict.update(
getattr(erp5.portal_type,
content_portal_type).importAllFromFilesystem(self,
erase_existing=erase_existing))
# XXX-arnau: NotImplementedErrror only until everything has been
# implemented
except (NotImplementedError, AttributeError):
LOG("ERP5Type.Tool.ComponentTool", WARNING, "Could not import %ss" % \
content_portal_type)
if REQUEST:
if failed_import_dict:
failed_import_formatted_list = []
for name, error in failed_import_dict.iteritems():
failed_import_formatted_list.append("%s (%s)" % (name, error))
message = "The following component could not be imported: %s" % \
', '.join(failed_import_formatted_list)
else:
message = "All components were successfully imported " \
"from filesystem to ZODB."
return self.Base_redirect('view',
keep_items={'portal_status_message': message})
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