Commit bd76f014 authored by Ayush Tiwari's avatar Ayush Tiwari

erp5_catalog: Conversion script to convert ZSQL Method and PythonScript to ERP5 objects

Also, Update BusinessTemplate installation with updated filter_dict
This removes the need to copy-patch or if-else on meta_type of catalog.
Use dynamic migration while installing the catalog method objects for
bt5.

Note : here we use conversion method for python script but dynamic migration for
ZSQL Methods. This is necessary because after the conversion to erp5 object, we need
to compile the body to generate code object for python script.
By just changing the class, this was not possible.

erp5_catalog: Simplify bt5 installation
parent 6dd33716
......@@ -153,12 +153,12 @@ SEPARATELY_EXPORTED_PROPERTY_DICT = {
def _getCatalog(acquisition_context):
"""
Return the id of the SQLCatalog which correspond to the current BT.
Return the id of the Catalog which correspond to the current BT.
"""
catalog_method_id_list = acquisition_context.getTemplateCatalogMethodIdList()
if len(catalog_method_id_list) == 0:
try:
return acquisition_context.getPortalObject().portal_catalog.objectIds('SQLCatalog')[0]
return acquisition_context.getPortalObject().portal_catalog.objectIds()[0]
except IndexError:
return None
catalog_method_id = catalog_method_id_list[0]
......@@ -1462,7 +1462,7 @@ class ObjectTemplateItem(BaseTemplateItem):
# an object which cannot (e.g. External Method).
LOG('BusinessTemplate', WARNING,
'could not restore %r in %r' % (subobject_id, obj))
if obj.meta_type in ('Z SQL Method',):
if obj.meta_type in ('Z SQL Method', 'ERP5 SQL Method'):
fixZSQLMethod(portal, obj)
# portal transforms specific initialization
elif obj.meta_type in ('Transform', 'TransformsChain'):
......@@ -1954,7 +1954,7 @@ class SkinTemplateItem(ObjectTemplateItem):
if not force and update_dict.get(relative_url) == 'nothing':
continue
folder = self.unrestrictedResolveValue(p, relative_url)
for obj in folder.objectValues(spec=('Z SQL Method',)):
for obj in folder.objectValues(spec=('Z SQL Method', 'ERP5 SQL Method')):
fixZSQLMethod(p, obj)
if folder.aq_parent.meta_type == 'CMF Skins Tool':
registerSkinFolder(skin_tool, folder)
......@@ -2894,14 +2894,23 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
"""Extracts properties for a given method in the catalog.
Returns a mapping of property name -> boolean """
method_properties = PersistentMapping()
for prop in catalog._properties:
property_list = list(catalog._properties)
if catalog.meta_type == 'ERP5 Catalog':
property_list = list(catalog.propertyMap())
for prop in property_list:
if prop.get('select_variable') == 'getCatalogMethodIds':
# In case the properties are defined via property sheet 'Catalog', the
# object would have two IDs if it is of type 'selection' or
# 'multiple_selection': 'id' and 'base_id', usage of base_id is preferred
# while building objects as it maintains consistency between the old
# catalog and new erp5 catalog
prop_id = prop.get('base_id', prop['id'])
if prop['type'] == 'selection' and \
getattr(catalog, prop['id']) == method_id:
method_properties[prop['id']] = 1
getattr(catalog, prop_id) == method_id:
method_properties[prop_id] = 1
elif prop['type'] == 'multiple selection' and \
method_id in getattr(catalog, prop['id']):
method_properties[prop['id']] = 1
method_id in getattr(catalog, prop_id):
method_properties[prop_id] = 1
return method_properties
def build(self, context, **kw):
......@@ -2920,7 +2929,8 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
method_id = obj.id
self._method_properties[method_id] = self._extractMethodProperties(
catalog, method_id)
filter = catalog.filter_dict.get(method_id, {})
filter_dict = catalog._getFilterDict()
filter = filter_dict.get(method_id, {})
self._is_filtered_archive[method_id] = filter.get('filtered', 0)
for method in catalog_method_filter_list:
property = method[8:-8]
......@@ -2986,6 +2996,32 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
force = kw.get('force')
values = []
# When the default catalog is of 'ERP5 Catalog' meta_type, its better to ..
# convert all the CatalogMethodTemplateItems in the current BT to the
# allowed types for ERP5 Catalog, i.e, to ERP5 SQLMethod and ERP5 Python Script
# and update the self._objects dict accordingly
if catalog.meta_type == 'ERP5 Catalog':
import erp5
from Products.ERP5.Extensions.CheckPortalTypes import changeObjectClass
# We need the dynamic portal_type classes for changing object classes
sql_class = getattr(erp5.portal_type, 'SQL Method')
script_class = getattr(erp5.portal_type, 'Python Script')
portal = self.getPortalObject()
# Will be modifying dict, so better to use .items()
# XXX: In python3 it should be .copy.items().
for path, obj in self._objects.items():
method = self.unrestrictedResolveValue(portal, path)
method_id = path.split('/')[-1]
if method.meta_type == 'Z SQL Method':
method = changeObjectClass(catalog, method_id, sql_class)
if method.meta_type == 'Script (Python)':
self.convertPythonScriptToERP5PythonScript(method)
method = self.unrestrictedResolveValue(portal, path)
new_obj = method.aq_base
self._objects[path] = new_obj
if force: # get all objects
values = self._objects.values()
else: # get only selected object
......@@ -3012,6 +3048,9 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
new_value.sort()
setattr(catalog, key, tuple(new_value))
if catalog.meta_type == 'ERP5 Catalog':
catalog.filter_dict = catalog._getFilterDict()
# Restore filter
if self._is_filtered_archive.get(method_id, 0):
expression = self._filter_expression_archive[method_id]
......@@ -3020,6 +3059,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
expr_instance = Expression(expression)
else:
expr_instance = None
if catalog.meta_type == 'SQLCatalog':
catalog.filter_dict[method_id] = PersistentMapping()
catalog.filter_dict[method_id]['filtered'] = 1
catalog.filter_dict[method_id]['expression'] = expression
......@@ -3085,15 +3125,26 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
values.append(value)
for obj in values:
method_id = obj.id
property_list = list(catalog._properties)
if catalog.meta_type == 'ERP5 Catalog':
property_list = list(catalog.propertyMap())
# remove method references in portal_catalog
for catalog_prop in catalog._properties:
for catalog_prop in property_list:
if catalog_prop.get('select_variable') == 'getCatalogMethodIds'\
and catalog_prop['type'] == 'multiple selection':
old_value = getattr(catalog, catalog_prop['id'], ())
# In case the properties are defined via property sheet 'Catalog', the
# object would have two IDs if it is of type 'selection' or
# 'multiple_selection': 'id' and 'base_id', usage of base_id is preferred
# while building objects as it maintains consistency between the old
# catalog and new erp5 catalog
catalog_prop_id = catalog_prop.get('base_id', catalog_prop['id'])
old_value = getattr(catalog, catalog_prop_id, ())
if method_id in old_value:
new_value = list(old_value)
new_value.remove(method_id)
setattr(catalog, catalog_prop['id'], new_value)
# Better to set the attribute value as tuple as it would be consistent
# with both SQL Catalog and ERP5 Catalog.
setattr(catalog, catalog_prop_id, tuple(new_value))
if method_id in catalog.filter_dict:
del catalog.filter_dict[method_id]
......
......@@ -1723,6 +1723,149 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
for obj in tool.objectValues():
obj.migrateToPortalTypeClass()
def convertPythonScriptToERP5PythonScript(self, python_script):
"""
Converts object with meta_type 'Script (Python)' to ERP5 Python Script
and moves all the properties and id to the new object.
Also, deletes the initial object.
Params:
python_script: Should be a python script inside ERP5 Catalog.
It is forced for the aq_parent to be an ERP5 Catalog.
"""
method_parent = python_script.aq_parent
if not method_parent.meta_type in ['ERP5 Catalog', 'SQLCatalog']:
return
erp5_catalog = method_parent
if not python_script: return None
# Filter only the objects which are of 'Script (Python)' meta_type
if python_script.meta_type == "Script (Python)":
script_id = python_script.id
title = python_script.title
code = python_script._body
parameter = python_script._params
_v_change = python_script._v_change
# Delete the python_script object from ther erp5_catalog
erp5_catalog.manage_delObjects(ids=script_id)
# Create new Python Script object inside erp5_catalog from the info data
# of the zope python script object.
erp5_python_script = erp5_catalog.newContent(portal_type='Python Script', \
id = script_id )
erp5_python_script.title = title
# Calling setter function for body would also compile the code body
erp5_python_script._setBody(code)
erp5_python_script._setParameterSignature(parameter)
erp5_python_script._v_change = _v_change
# Update filter properies only if SQL Catalog exists, in other case the
# updating of filter dict for the current object would be handled while
# installation itself.
try:
catalog = self.portal_catalog.getSQLCatalog()
if not catalog:
return
if catalog.meta_type != 'SQLCatalog':
return
filter_dict = catalog.filter_dict
except AttributeError:
return
else:
if script_id in filter_dict.keys():
filter_ = filter_dict[script_id]
erp5_python_script.setFiltered(filter_['filtered'])
erp5_python_script.setTypeList(filter_['type'])
erp5_python_script.setExpressionCacheKeyList(filter_['expression_cache_key'])
erp5_python_script.setExpression(filter_['expression'])
erp5_python_script.setExpressionInstance(filter_['expression_instance'])
else:
return
def convertSQLMethodToERP5SQLMethod(self, method):
"""
Converts the SQL Method(SQL) objects with all its properties and id to an
ERP5 SQL Method object.
Params:
method: Should be an sql method inside ERP5 Catalog.
It is forced for the aq_parent to be an ERP5 Catalog.
"""
obj_parent = method.aq_parent
# Only convert for objects having aq_parent
if not obj_parent.meta_type in ['ERP5 Catalog', 'SQLCatalog']:
return
erp5_catalog = obj_parent
if not method: return
if method.meta_type == "Z SQL Method":
sql_method = method
method_id = sql_method.id
title = sql_method.title
connection_id = sql_method.connection_id
connection_hook = sql_method.connection_hook
max_rows_ = sql_method.max_rows_
max_cache_ = sql_method.max_cache_
cache_time_ = sql_method.cache_time_
allow_simple_one_argument_traversal = sql_method.allow_simple_one_argument_traversal
class_file_ = sql_method.class_file_
class_name_ = sql_method.class_name_
arguments_src = sql_method.arguments_src
template = sql_method.src
# Delete old object and create a new object with same id
erp5_catalog.manage_delObjects(ids=method_id)
erp5_sql_method = erp5_catalog.newContent(portal_type='SQL Method',\
id = method_id)
# Update properties and attributes of erp5_sql_catalog with the info
# data of same attributes of sql_method
erp5_sql_method.title = title
erp5_sql_method.setConnectionId(connection_id)
erp5_sql_method.setSrc(template)
# Update advanced attributes for the SQL Method
erp5_sql_method.setConnectionHook(connection_hook)
erp5_sql_method.setMaxRows(max_rows_)
erp5_sql_method.setMaxCache(max_cache_)
erp5_sql_method.setCacheTime(cache_time_)
erp5_sql_method.setAllowSimpleOneArgumentTraversal(\
allow_simple_one_argument_traversal)
erp5_sql_method.setClassFile(class_file_)
erp5_sql_method.setClassName(class_name_)
# Update argument at last cause this will update other attributes by
# calling manage_edit for SQLMethod in ZRDB.DA
erp5_sql_method._setArgumentsSrc(arguments_src)
# Delete sql_method object from erp5_catalog and update the Id of
# erp5_catalog_object with the Id of sql_method
#erp5_catalog._delOb(id=method_id)
#erp5_sql_method.manage_renameObject(method_id)
# Update filter properies only if SQL Catalog exists, in other case the
# updating of filter dict for the current object would be handled while
# installation itself.
try:
catalog = self.portal_catalog.getSQLCatalog()
if not catalog:
return
# Only carry out updation of filter_dict when SQL Catalog still exists
if catalog.meta_type != 'SQLCatalog':
return
filter_dict = catalog.filter_dict
except AttributeError:
return
else:
if method_id in filter_dict.keys():
filter_ = filter_dict[method_id]
erp5_sql_method.setFiltered(filter_['filtered'])
erp5_sql_method.setTypeList(filter_['type'])
erp5_sql_method.setExpressionCacheKeyList(filter_['expression_cache_key'])
erp5_sql_method.setExpression(filter_['expression'])
erp5_sql_method.setExpressionInstance(filter_['expression_instance'])
else:
pass
else:
return
Globals.InitializeClass(ERP5Site)
def getBootstrapDirectory():
......
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