Commit 9c408f22 authored by Arnaud Fontaine's avatar Arnaud Fontaine

WIP: ZODB Components: Likewise Document, add Mixin (erp5.component.mixin) and...

WIP: ZODB Components: Likewise Document, add Mixin (erp5.component.mixin) and Interface (erp5.component.interface).

* One Mixin/Interface class per ZODB Component.
  => Already the case for FS Mixin, not for Interfaces.
* ZODB Components module name ('reference' property) and class name:
  + Mixin: FooMixin.
  + Interface: IFoo.

Rationale:
  + Avoid current FS hacks: registry (Mixins, mixin_class_registry) or import
    all classes explicitly in __init__.py (Products.ERP5Type.interfaces).
  + Consistent naming.
  + Consistent with ZODB Documents Components.

TODO BEFORE MERGING:
  + Add Unit Tests.
parent ba3ad323
...@@ -1160,6 +1160,14 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -1160,6 +1160,14 @@ class ObjectTemplateItem(BaseTemplateItem):
""" """
pass pass
def afterUninstall(self):
"""
Uninstallation hook.
Called right before returning in "uninstall" method.
Can be overridden by subclasses.
"""
pass
def onNewObject(self, obj): def onNewObject(self, obj):
""" """
Installation hook. Installation hook.
...@@ -1642,6 +1650,7 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -1642,6 +1650,7 @@ class ObjectTemplateItem(BaseTemplateItem):
# object is already backup and/or removed # object is already backup and/or removed
pass pass
BaseTemplateItem.uninstall(self, context, **kw) BaseTemplateItem.uninstall(self, context, **kw)
self.afterUninstall()
class PathTemplateItem(ObjectTemplateItem): class PathTemplateItem(ObjectTemplateItem):
""" """
...@@ -3795,7 +3804,7 @@ class ModuleTemplateItem(BaseTemplateItem): ...@@ -3795,7 +3804,7 @@ class ModuleTemplateItem(BaseTemplateItem):
pass pass
# XXX-arnau: when everything has been migrated to Components, this class # XXX-arnau: when everything has been migrated to Components, this class
# should be renamed to DocumentTemplateItem # should be removed and only _ZodbComponentTemplateItem should remain
class FilesystemDocumentTemplateItem(BaseTemplateItem): class FilesystemDocumentTemplateItem(BaseTemplateItem):
local_file_reader_name = staticmethod(readLocalDocument) local_file_reader_name = staticmethod(readLocalDocument)
local_file_writer_name = staticmethod(writeLocalDocument) local_file_writer_name = staticmethod(writeLocalDocument)
...@@ -4003,12 +4012,6 @@ class FilesystemToZodbTemplateItem(FilesystemDocumentTemplateItem, ...@@ -4003,12 +4012,6 @@ class FilesystemToZodbTemplateItem(FilesystemDocumentTemplateItem,
return FilesystemDocumentTemplateItem._importFile(self, file_name, return FilesystemDocumentTemplateItem._importFile(self, file_name,
*args, **kw) *args, **kw)
def afterUninstall(self, already_migrated=False):
"""
Hook called after uninstall
"""
pass
def uninstall(self, *args, **kw): def uninstall(self, *args, **kw):
# Only for uninstall, the path of objects can be given as a # Only for uninstall, the path of objects can be given as a
# parameter, otherwise it fallbacks on '_archive' # parameter, otherwise it fallbacks on '_archive'
...@@ -4018,14 +4021,11 @@ class FilesystemToZodbTemplateItem(FilesystemDocumentTemplateItem, ...@@ -4018,14 +4021,11 @@ class FilesystemToZodbTemplateItem(FilesystemDocumentTemplateItem,
else: else:
object_keys = self._archive.keys() object_keys = self._archive.keys()
already_migrated = self._is_already_migrated(object_keys) if self._is_already_migrated(object_keys):
if already_migrated:
ObjectTemplateItem.uninstall(self, *args, **kw) ObjectTemplateItem.uninstall(self, *args, **kw)
else: else:
FilesystemDocumentTemplateItem.uninstall(self, *args, **kw) FilesystemDocumentTemplateItem.uninstall(self, *args, **kw)
self.afterUninstall(already_migrated)
def remove(self, context, **kw): def remove(self, context, **kw):
""" """
Conversion of magically uniqued paths to real ones Conversion of magically uniqued paths to real ones
...@@ -4207,9 +4207,71 @@ class ConstraintTemplateItem(FilesystemDocumentTemplateItem): ...@@ -4207,9 +4207,71 @@ class ConstraintTemplateItem(FilesystemDocumentTemplateItem):
local_file_importer_name = staticmethod(importLocalConstraint) local_file_importer_name = staticmethod(importLocalConstraint)
local_file_remover_name = staticmethod(removeLocalConstraint) local_file_remover_name = staticmethod(removeLocalConstraint)
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent class _ZodbComponentTemplateItem(ObjectTemplateItem):
@staticmethod
def _getZodbObjectId(id):
raise NotImplementedError
def isKeepWorkflowObjectLastHistoryOnly(self, path):
"""
Component Validation Workflow last History of ZODB Components must always be
kept, without explicitly adding them to the field which requires an extra
action for developers
"""
return True
def _removeAllButLastWorkflowHistory(self, obj):
"""
Only export the last state of component_validation_workflow, because only
the source code and its state to load it is necessary for ZODB Components
and too much history would be exported (edit_workflow)
"""
for wf_id in obj.workflow_history.keys():
if wf_id != 'component_validation_workflow':
del obj.workflow_history[wf_id]
continue
wf_history = obj.workflow_history[wf_id][-1]
# Remove useless modifcation 'time' and 'actor' (conflicts with VCSs)
wf_history.pop('time', None)
wf_history.pop('actor', None)
wf_history.pop('comment', None)
obj.workflow_history[wf_id] = WorkflowHistoryList([wf_history])
def afterInstall(self):
"""
Reset component on the fly, because it is possible that those components
are required in the middle of the transaction. For example:
- A method in a component is called while installing.
- A document component is used in a different business template, and
those business templates are installed in a single transaction by
upgrader.
This reset is called at most 3 times in one business template
installation. (for Document, Test, Extension)
"""
self.portal_components.reset(force=True)
def afterUninstall(self):
self.portal_components.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
from Products.ERP5Type.Core.InterfaceComponent import InterfaceComponent
class InterfaceTemplateItem(_ZodbComponentTemplateItem):
@staticmethod
def _getZodbObjectId(id):
return InterfaceComponent.getIdPrefix() + '.' + id
from Products.ERP5Type.Core.MixinComponent import MixinComponent
class MixinTemplateItem(_ZodbComponentTemplateItem):
@staticmethod
def _getZodbObjectId(id):
return MixinComponent.getIdPrefix() + '.' + id
class DocumentTemplateItem(FilesystemToZodbTemplateItem): from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class DocumentTemplateItem(FilesystemToZodbTemplateItem,
_ZodbComponentTemplateItem):
""" """
Documents are now stored in ZODB rather than on the filesystem. However, Documents are now stored in ZODB rather than on the filesystem. However,
some Business Templates may still have filesystem Documents which need to be some Business Templates may still have filesystem Documents which need to be
...@@ -4230,12 +4292,14 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem): ...@@ -4230,12 +4292,14 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
This allows to keep Git history and having readable source code instead of This allows to keep Git history and having readable source code instead of
being crippled into an XML file being crippled into an XML file
""" """
_tool_id = 'portal_components'
@staticmethod @staticmethod
def _getZodbObjectId(id): def _getZodbObjectId(id):
return DocumentComponent.getIdPrefix() + '.' + id return DocumentComponent.getIdPrefix() + '.' + id
## All the methods/attributes below are for FS compatibility *only* and
## should be removed when all bt5s have been migrated
_tool_id = 'portal_components'
@staticmethod @staticmethod
def _getFilesystemPath(class_id): def _getFilesystemPath(class_id):
from App.config import getConfiguration from App.config import getConfiguration
...@@ -4250,25 +4314,6 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem): ...@@ -4250,25 +4314,6 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
action for developers action for developers
""" """
return path.startswith(self._tool_id + '/') return path.startswith(self._tool_id + '/')
def _removeAllButLastWorkflowHistory(self, obj):
"""
Only export the last state of component_validation_workflow, because only
the source code and its state to load it is necessary for ZODB Components
and too much history would be exported (edit_workflow)
"""
for wf_id in obj.workflow_history.keys():
if wf_id != 'component_validation_workflow':
del obj.workflow_history[wf_id]
continue
wf_history = obj.workflow_history[wf_id][-1]
# Remove useless modifcation 'time' and 'actor' (conflicts with VCSs)
wf_history.pop('time', None)
wf_history.pop('actor', None)
wf_history.pop('comment', None)
obj.workflow_history[wf_id] = WorkflowHistoryList([wf_history])
# XXX temporary should be eliminated from here # XXX temporary should be eliminated from here
def _importFile(self, file_name, file_obj): def _importFile(self, file_name, file_obj):
...@@ -4289,6 +4334,7 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem): ...@@ -4289,6 +4334,7 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
if not self._archive: if not self._archive:
return return
# After running the migration script, update bt5 property accordingly
if not self._is_already_migrated(self._archive.keys()): if not self._is_already_migrated(self._archive.keys()):
document_id_list = self.getTemplateIdList() document_id_list = self.getTemplateIdList()
if document_id_list[0] not in getattr(context.getPortalObject(), if document_id_list[0] not in getattr(context.getPortalObject(),
...@@ -4307,23 +4353,16 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem): ...@@ -4307,23 +4353,16 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
issue as there are not so many Documents in bt5... issue as there are not so many Documents in bt5...
""" """
if self._is_already_migrated(self._objects.keys()): if self._is_already_migrated(self._objects.keys()):
ObjectTemplateItem.install(self, context, **kw) _ZodbComponentTemplateItem.install(self, context, **kw)
# Reset component on the fly, because it is possible that those
# components are required in the middle of the transaction. For example:
# - A method in a component is called while installing.
# - A document component is used in a different business template,
# and those business templates are installed in a single transaction
# by upgrader.
# This reset is called at most 3 times in one business template
# installation. (for Document, Test, Extension)
self.portal_components.reset(force=True)
else: else:
FilesystemDocumentTemplateItem.install(self, context, **kw) FilesystemDocumentTemplateItem.install(self, context, **kw)
def afterUninstall(self, already_migrated=False): _removeAllButLastWorkflowHistory = _ZodbComponentTemplateItem._removeAllButLastWorkflowHistory
if already_migrated:
self.portal_components.reset(force=True, # Only for ObjectTemplateItem (ZODB Components) and thus no need to check
reset_portal_type_at_transaction_boundary=True) # whether they have already been migrated or not
afterInstall = _ZodbComponentTemplateItem.afterInstall
afterUninstall = _ZodbComponentTemplateItem.afterUninstall
from Products.ERP5Type.Core.ExtensionComponent import ExtensionComponent from Products.ERP5Type.Core.ExtensionComponent import ExtensionComponent
...@@ -5117,6 +5156,10 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -5117,6 +5156,10 @@ Business Template is a set of definitions, such as skins, portal types and categ
ModuleTemplateItem(self.getTemplateModuleIdList()) ModuleTemplateItem(self.getTemplateModuleIdList())
self._document_item = \ self._document_item = \
DocumentTemplateItem(self.getTemplateDocumentIdList()) DocumentTemplateItem(self.getTemplateDocumentIdList())
self._interface_item = \
InterfaceTemplateItem(self.getTemplateInterfaceIdList())
self._mixin_item = \
MixinTemplateItem(self.getTemplateMixinIdList())
self._property_sheet_item = \ self._property_sheet_item = \
PropertySheetTemplateItem(self.getTemplatePropertySheetIdList(), PropertySheetTemplateItem(self.getTemplatePropertySheetIdList(),
context=self) context=self)
...@@ -5938,6 +5981,8 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -5938,6 +5981,8 @@ Business Template is a set of definitions, such as skins, portal types and categ
'PropertySheet' : '_property_sheet_item', 'PropertySheet' : '_property_sheet_item',
'Constraint' : '_constraint_item', 'Constraint' : '_constraint_item',
'Document' : '_document_item', 'Document' : '_document_item',
'Interface': '_interface_item',
'Mixin': '_mixin_item',
'Extension' : '_extension_item', 'Extension' : '_extension_item',
'Test' : '_test_item', 'Test' : '_test_item',
'Role' : '_role_item', 'Role' : '_role_item',
...@@ -6048,7 +6093,8 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -6048,7 +6093,8 @@ Business Template is a set of definitions, such as skins, portal types and categ
# Text objects (no need to export them into XML) # Text objects (no need to export them into XML)
# XXX Bad naming # XXX Bad naming
item_list_3 = ['_document_item', '_property_sheet_item', item_list_3 = ['_document_item', '_interface_item', '_mixin_item',
'_property_sheet_item',
'_constraint_item', '_extension_item', '_constraint_item', '_extension_item',
'_test_item', '_message_translation_item',] '_test_item', '_message_translation_item',]
......
<?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_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</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>view</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>View</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}/ComponentMixin_view</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python: object is not None and not object.isWebMode()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</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>view</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>1.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>View</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}/ComponentMixin_view</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python: object is not None and not object.isWebMode()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -51,6 +51,8 @@ ...@@ -51,6 +51,8 @@
<portal_type id="Component Tool"> <portal_type id="Component Tool">
<item>Document Component</item> <item>Document Component</item>
<item>Extension Component</item> <item>Extension Component</item>
<item>Interface Component</item>
<item>Mixin Component</item>
<item>Test Component</item> <item>Test Component</item>
</portal_type> </portal_type>
<portal_type id="Contribution Registry Tool"> <portal_type id="Contribution Registry Tool">
......
...@@ -41,6 +41,12 @@ ...@@ -41,6 +41,12 @@
<portal_type id="Extension Component"> <portal_type id="Extension Component">
<item>SortIndex</item> <item>SortIndex</item>
</portal_type> </portal_type>
<portal_type id="Interface Component">
<item>SortIndex</item>
</portal_type>
<portal_type id="Mixin Component">
<item>SortIndex</item>
</portal_type>
<portal_type id="Property Existence Constraint"> <portal_type id="Property Existence Constraint">
<item>ConstraintType</item> <item>ConstraintType</item>
</portal_type> </portal_type>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Type" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_property_domain_dict</string> </key>
<value>
<dictionary>
<item>
<key> <string>short_title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>acquire_local_roles</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>content_icon</string> </key>
<value> <string>web_page.png</string> </value>
</item>
<item>
<key> <string>content_meta_type</string> </key>
<value> <string>ERP5 Text Document</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An Interface Component is just a specific Document Component for Zope Interfaces in ZODB. </string> </value>
</item>
<item>
<key> <string>factory</string> </key>
<value> <string>addDocumentComponent</string> </value>
</item>
<item>
<key> <string>filter_content_types</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>InterfaceComponent</string> </value>
</item>
<item>
<key> <string>type_interface</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>short_title</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>title</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Type" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_property_domain_dict</string> </key>
<value>
<dictionary>
<item>
<key> <string>short_title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>acquire_local_roles</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>content_icon</string> </key>
<value> <string>web_page.png</string> </value>
</item>
<item>
<key> <string>content_meta_type</string> </key>
<value> <string>ERP5 Text Document</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>A Mixin Component is just a specific Document Component for ERP5 mixins in ZODB. </string> </value>
</item>
<item>
<key> <string>factory</string> </key>
<value> <string>addDocumentComponent</string> </value>
</item>
<item>
<key> <string>filter_content_types</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Mixin Component</string> </value>
</item>
<item>
<key> <string>init_script</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>MixinComponent</string> </value>
</item>
<item>
<key> <string>type_interface</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>type_mixin</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>short_title</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<tuple>
<global name="TranslationInformation" module="Products.ERP5Type.TranslationProviderBase"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>domain_name</string> </key>
<value> <string>erp5_content</string> </value>
</item>
<item>
<key> <string>property_name</string> </key>
<value> <string>title</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -107,6 +107,10 @@ ...@@ -107,6 +107,10 @@
<type>Extension Component</type> <type>Extension Component</type>
<workflow>component_validation_workflow, dynamic_class_generation_interaction_workflow, edit_workflow</workflow> <workflow>component_validation_workflow, dynamic_class_generation_interaction_workflow, edit_workflow</workflow>
</chain> </chain>
<chain>
<type>Interface Component</type>
<workflow>component_validation_workflow, dynamic_class_generation_interaction_workflow, edit_workflow</workflow>
</chain>
<chain> <chain>
<type>Mapped Value</type> <type>Mapped Value</type>
<workflow>edit_workflow</workflow> <workflow>edit_workflow</workflow>
...@@ -115,6 +119,10 @@ ...@@ -115,6 +119,10 @@
<type>Memcached Plugin</type> <type>Memcached Plugin</type>
<workflow>memcached_plugin_interaction_workflow</workflow> <workflow>memcached_plugin_interaction_workflow</workflow>
</chain> </chain>
<chain>
<type>Mixin Component</type>
<workflow>component_validation_workflow, dynamic_class_generation_interaction_workflow, edit_workflow</workflow>
</chain>
<chain> <chain>
<type>Predicate</type> <type>Predicate</type>
<workflow>edit_workflow</workflow> <workflow>edit_workflow</workflow>
......
...@@ -64,6 +64,8 @@ ...@@ -64,6 +64,8 @@
<list> <list>
<string>my_template_role_list</string> <string>my_template_role_list</string>
<string>my_template_site_property_id_list</string> <string>my_template_site_property_id_list</string>
<string>my_template_interface_id_list</string>
<string>my_template_mixin_id_list</string>
<string>my_template_document_id_list</string> <string>my_template_document_id_list</string>
<string>my_template_property_sheet_id_list</string> <string>my_template_property_sheet_id_list</string>
<string>my_template_extension_id_list</string> <string>my_template_extension_id_list</string>
......
<?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_interface_id_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>Interface Classes</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 />
]]></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="LinesField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_template_mixin_id_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>Mixin Classes</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 />
]]></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>
...@@ -72,6 +72,8 @@ ...@@ -72,6 +72,8 @@
<list> <list>
<string>Document Component</string> <string>Document Component</string>
<string>Extension Component</string> <string>Extension Component</string>
<string>Interface Component</string>
<string>Mixin Component</string>
<string>Test Component</string> <string>Test Component</string>
</list> </list>
</value> </value>
......
...@@ -71,10 +71,18 @@ ...@@ -71,10 +71,18 @@
<list> <list>
<string>Document Component</string> <string>Document Component</string>
<string>Extension Component</string> <string>Extension Component</string>
<string>Interface Component</string>
<string>Mixin Component</string>
<string>Test Component</string> <string>Test Component</string>
</list> </list>
</value> </value>
</item> </item>
<item>
<key> <string>portal_type_group_filter</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>script_name</string> </key> <key> <string>script_name</string> </key>
<value> <value>
......
...@@ -85,8 +85,10 @@ Dynamic Category Property | view ...@@ -85,8 +85,10 @@ Dynamic Category Property | view
Extension Component | view Extension Component | view
Folder | view Folder | view
Id Tool | view Id Tool | view
Interface Component | view
Memcached Plugin | view Memcached Plugin | view
Memcached Tool | view Memcached Tool | view
Mixin Component | view
Predicate | view Predicate | view
Preference Tool Type | jump_property_sheets Preference Tool Type | jump_property_sheets
Preference Tool Type | view Preference Tool Type | view
......
...@@ -21,6 +21,8 @@ Category Tool | Base Category ...@@ -21,6 +21,8 @@ Category Tool | Base Category
Category | Category Category | Category
Component Tool | Document Component Component Tool | Document Component
Component Tool | Extension Component Component Tool | Extension Component
Component Tool | Interface Component
Component Tool | Mixin Component
Component Tool | Test Component Component Tool | Test Component
Contribution Registry Tool | Contribution Predicate Contribution Registry Tool | Contribution Predicate
Domain Tool | Base Domain Domain Tool | Base Domain
......
...@@ -48,9 +48,11 @@ Event ...@@ -48,9 +48,11 @@ Event
Extension Component Extension Component
Folder Folder
Id Tool Id Tool
Interface Component
Mapped Value Mapped Value
Memcached Plugin Memcached Plugin
Memcached Tool Memcached Tool
Mixin Component
Movement Movement
Notification Tool Notification Tool
Order Tool Order Tool
......
...@@ -12,6 +12,8 @@ Category Related Membership State Constraint | ConstraintType ...@@ -12,6 +12,8 @@ Category Related Membership State Constraint | ConstraintType
Content Existence Constraint | ConstraintType Content Existence Constraint | ConstraintType
Document Component | SortIndex Document Component | SortIndex
Extension Component | SortIndex Extension Component | SortIndex
Interface Component | SortIndex
Mixin Component | SortIndex
Property Existence Constraint | ConstraintType Property Existence Constraint | ConstraintType
Property Type Validity Constraint | ConstraintType Property Type Validity Constraint | ConstraintType
Python Script | CatalogFilter Python Script | CatalogFilter
......
...@@ -32,8 +32,14 @@ Dynamic Category Property | dynamic_class_generation_interaction_workflow ...@@ -32,8 +32,14 @@ Dynamic Category Property | dynamic_class_generation_interaction_workflow
Extension Component | component_validation_workflow Extension Component | component_validation_workflow
Extension Component | dynamic_class_generation_interaction_workflow Extension Component | dynamic_class_generation_interaction_workflow
Extension Component | edit_workflow Extension Component | edit_workflow
Interface Component | component_validation_workflow
Interface Component | dynamic_class_generation_interaction_workflow
Interface Component | edit_workflow
Mapped Value | edit_workflow Mapped Value | edit_workflow
Memcached Plugin | memcached_plugin_interaction_workflow Memcached Plugin | memcached_plugin_interaction_workflow
Mixin Component | component_validation_workflow
Mixin Component | dynamic_class_generation_interaction_workflow
Mixin Component | edit_workflow
Predicate | edit_workflow Predicate | edit_workflow
Preference | edit_workflow Preference | edit_workflow
Preference | preference_workflow Preference | preference_workflow
......
<?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 ids of Interfaces used by this template</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_interface_id_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>
<?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 ids of Mixins used by this template</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_mixin_id_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>
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
# Arnaud Fontaine <arnaud.fontaine@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class InterfaceComponent(DocumentComponent):
"""
ZODB Component for interfaces
"""
meta_type = 'ERP5 Interface Component'
portal_type = 'Interface Component'
@staticmethod
def _getDynamicModuleNamespace():
return 'erp5.component.interface'
@staticmethod
def getIdPrefix():
return 'interface'
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
# Arnaud Fontaine <arnaud.fontaine@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class MixinComponent(DocumentComponent):
"""
ZODB Component for mixins
"""
meta_type = 'ERP5 Mixin Component'
portal_type = 'Mixin Component'
@staticmethod
def _getDynamicModuleNamespace():
return 'erp5.component.mixin'
@staticmethod
def getIdPrefix():
return 'mixin'
...@@ -200,36 +200,6 @@ class TypesTool(TypeProvider): ...@@ -200,36 +200,6 @@ class TypesTool(TypeProvider):
return None return None
return getattr(self, portal_type, None) return getattr(self, portal_type, None)
security.declareProtected(Permissions.AccessContentsInformation, 'getDocumentTypeList')
def getDocumentTypeList(self):
"""
Return a list of Document types (including filesystem and ZODB Component
Documents) that can be used as Base classes
"""
from Products.ERP5Type import document_class_registry
document_type_set = set(document_class_registry)
import erp5.component.document
portal = self.getPortalObject()
version_priority_set = set(portal.getVersionPriorityNameList())
# objectValues should not be used for a large number of objects, but
# this is only done upon reset, moreover using the Catalog is too risky
# as it lags behind and depends upon objects being reindexed
for component in portal.portal_components.objectValues(portal_type='Document Component'):
# Only consider modified or validated states as state transition will
# be handled by component_validation_workflow which will take care of
# updating the registry
validation_state_tuple = component.getValidationState()
if validation_state_tuple in ('modified', 'validated'):
version = component.getVersion(validated_only=True)
# The versions should have always been set on ERP5Site property
# beforehand
if version in version_priority_set:
document_type_set.add(component.getReference(validated_only=True))
return sorted(document_type_set)
security.declareProtected(Permissions.AccessContentsInformation, 'getPortalTypeClass') security.declareProtected(Permissions.AccessContentsInformation, 'getPortalTypeClass')
def getPortalTypeClass(self, context, temp=False): def getPortalTypeClass(self, context, temp=False):
""" """
...@@ -258,13 +228,44 @@ class TypesTool(TypeProvider): ...@@ -258,13 +228,44 @@ class TypesTool(TypeProvider):
module = erp5.portal_type module = erp5.portal_type
return getattr(module, portal_type, None) return getattr(module, portal_type, None)
def _getTypeList(self, component_portal_type, fs_type_list):
portal = self.getPortalObject()
version_priority_set = set(portal.getVersionPriorityNameList())
# objectValues should not be used for a large number of objects, but
# this is only done upon reset, moreover using the Catalog is too risky
# as it lags behind and depends upon objects being reindexed
type_set = set(fs_type_list)
for component in portal.portal_components.objectValues(portal_type=component_portal_type):
# Only consider modified or validated states as state transition will
# be handled by component_validation_workflow which will take care of
# updating the registry
validation_state_tuple = component.getValidationState()
if validation_state_tuple in ('modified', 'validated'):
version = component.getVersion(validated_only=True)
# The versions should have always been set on ERP5Site property
# beforehand
if version in version_priority_set:
type_set.add(component.getReference(validated_only=True))
return sorted(type_set)
security.declareProtected(Permissions.AccessContentsInformation, 'getDocumentTypeList')
def getDocumentTypeList(self):
"""
Return a list of Document types (including filesystem and ZODB Component
Documents) that can be used as Base classes
"""
from Products.ERP5Type import document_class_registry
return self._getTypeList('Document Component', document_class_registry)
security.declareProtected(Permissions.AccessContentsInformation, 'getMixinTypeList') security.declareProtected(Permissions.AccessContentsInformation, 'getMixinTypeList')
def getMixinTypeList(self): def getMixinTypeList(self):
""" """
Return a list of class names that can be used as Mixins Return a list of class names that can be used as Mixins
""" """
from Products.ERP5Type import mixin_class_registry from Products.ERP5Type import mixin_class_registry
return sorted(mixin_class_registry) return self._getTypeList('Mixin Component', mixin_class_registry)
security.declareProtected(Permissions.AccessContentsInformation, 'getInterfaceTypeList') security.declareProtected(Permissions.AccessContentsInformation, 'getInterfaceTypeList')
def getInterfaceTypeList(self): def getInterfaceTypeList(self):
...@@ -272,7 +273,9 @@ class TypesTool(TypeProvider): ...@@ -272,7 +273,9 @@ class TypesTool(TypeProvider):
Return a list of class names that can be used as Interfaces Return a list of class names that can be used as Interfaces
""" """
from Products.ERP5Type import interfaces from Products.ERP5Type import interfaces
return [name for name, cls in inspect.getmembers(interfaces, inspect.isclass)] return self._getTypeList(
'Interface Component',
[name for name, _ in inspect.getmembers(interfaces, inspect.isclass)])
security.declareProtected(Permissions.ModifyPortalContent, security.declareProtected(Permissions.ModifyPortalContent,
'resetDynamicDocumentsOnceAtTransactionBoundary') 'resetDynamicDocumentsOnceAtTransactionBoundary')
......
...@@ -182,6 +182,10 @@ def initializeDynamicModules(): ...@@ -182,6 +182,10 @@ def initializeDynamicModules():
holds ZODB Component packages holds ZODB Component packages
erp5.component.document: erp5.component.document:
holds Document modules previously found in bt5 in $INSTANCE_HOME/Document holds Document modules previously found in bt5 in $INSTANCE_HOME/Document
erp5.component.interface:
holds Interface modules previously found in Products.NAME.interfaces
erp5.component.mixin:
holds Mixin modules previously found in Products.NAME.mixin
erp5.component.extension: erp5.component.extension:
holds Extension modules previously found in bt5 in holds Extension modules previously found in bt5 in
$INSTANCE_HOME/Extensions $INSTANCE_HOME/Extensions
...@@ -236,6 +240,12 @@ def initializeDynamicModules(): ...@@ -236,6 +240,12 @@ def initializeDynamicModules():
erp5.component.document = ComponentDynamicPackage('erp5.component.document', erp5.component.document = ComponentDynamicPackage('erp5.component.document',
'Document Component') 'Document Component')
erp5.component.interface = ComponentDynamicPackage('erp5.component.interface',
'Interface Component')
erp5.component.mixin = ComponentDynamicPackage('erp5.component.mixin',
'Mixin Component')
erp5.component.test = ComponentDynamicPackage('erp5.component.test', erp5.component.test = ComponentDynamicPackage('erp5.component.test',
'Test Component') 'Test Component')
finally: finally:
......
...@@ -201,9 +201,8 @@ def generatePortalTypeClass(site, portal_type_name): ...@@ -201,9 +201,8 @@ def generatePortalTypeClass(site, portal_type_name):
klass = getattr(module, type_class) klass = getattr(module, type_class)
except AttributeError: except AttributeError:
LOG("ERP5Type.dynamic", WARNING, LOG("ERP5Type.dynamic", WARNING,
"Could not get class '%s' in Component module '%s'" % \ "Could not get class '%s' in Component module %r, fallback on filesystem" %
(type_class, (type_class, module))
module))
if klass is None: if klass is None:
type_class_path = document_class_registry.get(type_class) type_class_path = document_class_registry.get(type_class)
...@@ -244,18 +243,58 @@ def generatePortalTypeClass(site, portal_type_name): ...@@ -244,18 +243,58 @@ def generatePortalTypeClass(site, portal_type_name):
# "Filled accessor holder list for portal_type %s (%s)" % \ # "Filled accessor holder list for portal_type %s (%s)" % \
# (portal_type_name, accessor_holder_list)) # (portal_type_name, accessor_holder_list))
mixin_path_list = [] mixin_class_list = []
if mixin_list: if mixin_list:
mixin_path_list = map(mixin_class_registry.__getitem__, mixin_list) # Only one Mixin class per ZODB Component (!= FS) where module_name ==
mixin_class_list = map(_importClass, mixin_path_list) # class_name, name ending with 'Mixin'.
#
# Rationale: same as Document/Interface; consistent naming; avoid a
# registry like there used to be with FS.
import erp5.component.mixin
for mixin in mixin_list:
mixin_module = erp5.component.mixin.find_load_module(mixin)
mixin_class = None
if mixin_module is not None:
try:
mixin_class = getattr(mixin_module, mixin)
except AttributeError:
LOG("ERP5Type.dynamic", WARNING,
"Could not get class '%s' in Component module %r, fallback on filesystem" %
(mixin, mixin_module))
if mixin_class is None:
mixin_class = _importClass(mixin_class_registry[mixin])
mixin_class_list.append(mixin_class)
base_class_list = [klass] + accessor_holder_list + mixin_class_list base_class_list = [klass] + accessor_holder_list + mixin_class_list
interface_class_list = [] interface_class_list = []
if interface_list: if interface_list:
from Products.ERP5Type import interfaces # Filesystem Interfaces may have defined several Interfaces in one file
interface_class_list = [getattr(interfaces, name) # but only *one* Interface per ZODB Component where module_name ==
for name in interface_list] # class_name, name starting with 'I'.
#
# Rationale: same as Document/Mixin; consistent naming; avoid a registry
# like there used to be for Mixin or importing all class in
# Products.ERP5Type.interfaces.__init__.py.
import erp5.component.interface
from Products.ERP5Type import interfaces as filesystem_interfaces
for interface in interface_list:
interface_module = erp5.component.interface.find_load_module(interface)
interface_class = None
if interface_module is not None:
try:
interface_class = getattr(interface_module, interface)
except AttributeError:
LOG("ERP5Type.dynamic", WARNING,
"Could not get class '%s' in Component module %r, fallback on filesystem" %
(interface, interface_module))
if interface_class is None:
interface_class = getattr(filesystem_interfaces, interface)
interface_class_list.append(interface_class)
if portal_type_name in core_portal_type_class_dict: if portal_type_name in core_portal_type_class_dict:
core_portal_type_class_dict[portal_type_name]['generating'] = False core_portal_type_class_dict[portal_type_name]['generating'] = False
......
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