My Archetypes-based content type can't be adde

2019-07-07 19:47发布

I'm developing an add-on package which introduces a few Archetypes-based content types; these are defined in the default profile of that package.

After (re-) installing my package in the Quick-Installer, I can see my types in the types tool; but I can't add them TTW, and they are not listed in the folder_constraintypes_form. I did select them in the "Allowed content types" multiselect list of the Folder portal type.

Since I got a ValueError from FactoryTypeInformation._getFactoryMethod in an bin/instance debug session, I "developed" Products.CMFPlone (branch 2.2) and changed the TypesTool.py like so:

from pprint import pprint                 # ADDED
...
class FactoryTypeInformation(TypeInformation):
    ...
    def _getFactoryMethod(self, container, check_security=1):
        if not self.product or not self.factory:
            raise ValueError, ('Product factory for %s was undefined' %
                               self.getId())
        pd = container.manage_addProduct  # ADDED
        p = container.manage_addProduct[self.product]
        self_product = self.product       # ADDED
        self_factory = self.factory       # ADDED
        m = getattr(p, self.factory, None)
        if m is None:
            pprint(locals())              # ADDED
            raise ValueError, ('Product factory for %s was invalid' %
                               self.getId())
        if not check_security:
            return m
        if getSecurityManager().validate(p, p, self.factory, m):
            return m
        raise AccessControl_Unauthorized( 'Cannot create %s' % self.getId() )

The debug session now looks like this:

>>> root = app.plone
>>> from Products.CMFCore.utils import getToolByName
>>> tmp_folder = root.temp
>>> type_name = 'MyType'
>>> types_tool = getToolByName(tmp_folder, 'portal_types')
>>> type_info = types_tool.getTypeInfo(type_name)
>>> type_info
<DynamicViewTypeInformation at /plone/portal_types/MyType>
>>> new_content_item = type_info._constructInstance(tmp_folder, 'shiny_new_object')
{'check_security': 0,
 'container': <ATFolder at /plone/temp>,
 'pd': <App.FactoryDispatcher.ProductDispatcher object at 0x227afd0>,
 'p': <App.FactoryDispatcher.FactoryDispatcher object at 0x7b97450>,
 'self': <DynamicViewTypeInformation at /plone/portal_types/MyType>,
 'm': None,
 'self_factory': 'addMyType',
 'self_product': 'MyCompany.MyProduct'}
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/zope/instances/zope-devel/src/Products.CMFCore/Products/CMFCore/TypesTool.py", line 551, in _constructInstance
    m = self._getFactoryMethod(container, check_security=0)
  File "/opt/zope/instances/zope-devel/src/Products.CMFCore/Products/CMFCore/TypesTool.py", line 467, in _getFactoryMethod
    self.getId())
ValueError: Product factory for MyType was invalid

So, the FactoryDispatcher lacks the necessary addMyType attribute. Probably my declarations are incomplete?

This is what I have:

config.py:

# -*- coding: utf-8 -*-
from Products.CMFCore.permissions import setDefaultRoles
from os import sep

from .permissions import (AddMyType,
        )

PROJECTNAME = "MyCompany.MyProduct"
PRODUCT_HOME = sep.join(__file__.split(sep)[:-1])

MANAGERS_ONLY = ('Manager',)
MANAGERS_AND_OWNER = ('Manager', 'Owner')

# Permissions
DEFAULT_ADD_CONTENT_PERMISSION = "Add portal content"
setDefaultRoles(DEFAULT_ADD_CONTENT_PERMISSION, MANAGERS_AND_OWNER)
ADD_CONTENT_PERMISSIONS = {
    'MyType': AddMyType,
}
for perm in ADD_CONTENT_PERMISSIONS.values():
    setDefaultRoles(perm, MANAGERS_ONLY)

content/mytype.py:

# -*- coding: utf-8 -*-
__author__ = """unknown <unknown>"""
__docformat__ = 'plaintext'

from AccessControl import ClassSecurityInfo
from zope.interface import implements
from ..interfaces import IMyType

from ..config import PROJECTNAME

from Products.ATContentTypes.content.base import ATCTContent
from Products.ATContentTypes.content.schemata import ATContentTypeSchema
from Products.ATContentTypes.content.base import registerATCT as registerType

MyType_schema = (
    ATContentTypeSchema.copy()
    )

class MyType(ATCTContent):
    """
    description of my type
    """
    security = ClassSecurityInfo()
    implements(IMyType)
    meta_type = 'MyType'
    _at_rename_after_creation = True

    schema = MyType_schema

registerType(MyType, PROJECTNAME)

interfaces.py:

# -*- coding: utf-8 -*-
"""Module where all interfaces, events and exceptions live."""

from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.interface import Interface

class ISupBetonqualiLayer(IDefaultBrowserLayer):
    """Marker interface that defines a browser layer."""

class IMyType(Interface):
    """Marker interface for .mytype.MyType
    """

permissions.py:

# -*- coding: utf-8 -*- vim: ts=8 sts=4 sw=4 si et tw=79
"""
Permissions
"""
AddMyType = 'MyCompany.MyProduct: Add MyType'

profiles/default/factorytool.xml:

<?xml version="1.0"?>
<object name="portal_factory" meta_type="Plone Factory Tool">
 <factorytypes>
  <type portal_type="MyType"/>
 </factorytypes>
</object>

profiles/default/rolemap.xml:

<?xml version="1.0"?>
<rolemap>
  <roles>
    <role name="MyAuthor"/>
  </roles>
  <permissions>
    <permission name="MyCompany.MyProduct: Add MyType" acquire="True">
      <role name="MyAuthor"/>
      <role name="Manager"/>
    </permission>
  </permissions>
</rolemap>

profiles/default/types.xml:

<?xml version="1.0"?>
<object name="portal_types"
        meta_type="Plone Types Tool">
 <object name="MyType"
         meta_type="Factory-based Type Information with dynamic views"/>
</object>

profiles/default/types/MyType.xml:

<?xml version="1.0"?>
<object name="MyType"
        meta_type="Factory-based Type Information with dynamic views"
        xmlns:i18n="http://xml.zope.org/namespaces/i18n">
 <property name="title">MyType</property>
 <property name="description">
 Some description text which is indeed visible in the types tool
 </property>
 <property name="content_icon">SomeExisting.png</property>
 <property name="content_meta_type">MyType</property>
 <property name="product">MyCompany.MyProduct</property>
 <property name="factory">addMyType</property>
 <property name="immediate_view">mytype_view</property>
 <property name="global_allow">True</property>
 <property name="filter_content_types">False</property>
 <property name="allowed_content_types">
 </property>
 <property name="allow_discussion">False</property>
 <property name="default_view">mytype_view</property>
 <property name="view_methods">
  <element value="base_view"/>
 </property>
 <property name="default_view_fallback">False</property>
 <alias from="(Default)" to="(dynamic view)"/>
 <alias from="index.html" to="(dynamic view)"/>
 <alias from="view" to="(selected layout)"/>
 <alias from="edit" to="base_edit"/>
 <alias from="properties" to="base_metadata"/>
 <action title="View"
         action_id="view"
         category="object"
         condition_expr=""
         url_expr="string:${object_url}/view"
         visible="True">
  <permission value="View"/>
 </action>
 <action title="Edit"
         action_id="edit"
         category="object"
         condition_expr="not:object/@@plone_lock_info/is_locked_for_current_user"
         url_expr="string:${object_url}/edit"
         visible="True">
  <permission value="Modify portal content"/>
 </action>
</object>
  • Should not Archetypes take care of creating that missing addMyType method?
  • What could make this fail?
  • Is there something obviously missing in my configuration?
  • The site contains Archtypes-based objects exclusively so far. Will I come into trouble if I add Dexterity-based types now? ''(I'm totally inexperienced with Dexterity)''

Before someone tells me to do so: I created a question in the Plone community forum already; no luck so far. If important information comes in on either page, I'll sync it.

1条回答
爷的心禁止访问
2楼-- · 2019-07-07 20:19

These are the missing parts to make your contenttype addable:

1.) Register the content-directory in MyCompany/MyProduct/configure.zcml by adding:

<include package=".content" />

2.) Add the file MyCompany/MyProduct/content/configure.zcml with this content:

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:five="http://namespaces.zope.org/five"
    i18n_domain="MyCompany.MyProduct">

  <class class=".mytype.MyType">
    <require
        permission="zope2.View"
        interface="..interfaces.IMyType"
        />
  </class>

</configure>

3.) Fix the then occurring syntax-error in MyCompany/MyProduct/content/mytype.py by replacing class MyType(*basecls) with class MyType(ATCTContent).

And last but not least remove the former attempts of making things work. Best would be to outsource the type to a dedicated pckg and create it with zopeskel, imo.

For the view-error occurring after adding a type, feel free to open a new quest ;-)

查看更多
登录 后发表回答