My AT content type can't be added TTW

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.

Any well-known gotchas, or any pointers, please?

Is it true that there is a hard requirement to add types in a migration step?
(Plone 4.3)

Thank you!

Unless your content types are not declared properly I can only think of two things.

  1. your logged in user does not have the rights to add this content type
  2. You are not in a folder (but in a smart folder or at Plone root)...

Yes, a permissions problem seems likely. I'm logged in with Manager rights, and of course (since I'm aware of the portal_types tool, and added my types to the Allowed content types of the Folder type, I added a Folder and tried to add to it.

However, my rolemap.xml is still quite empty; it simply contains a few roles, but no permissions yet. Do I really need special Add MyType ... permisson and MyType... roles for each of my types?

I started my Zope with bin/instance debug and tried:

>>> from Products.CMFCore.utils import getToolByName
>>> root = app.plone
>>> types_tool = getToolByName(root, 'portal_types')
>>> type_name = 'MyTypeOne'
>>> type_info = portal_types.getTypeInfo(type_name)
>>> type_info
<DynamicViewTypeInformation at /plone/portal_types/MyTypeOne>
>>> tmp_folder = root.temp
>>> new_content_item = type_info._constructInstance(tmp_folder, 'shiny_new_object')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/zope/eggs/Products.CMFCore-2.2.7-py2.7.egg/Products/CMFCore/TypesTool.py", line 546, in _constructInstance
m = self._getFactoryMethod(container, check_security=0)
  File "/opt/zope/eggs/Products.CMFCore-2.2.7-py2.7.egg/Products/CMFCore/TypesTool.py", line 462, in _getFactoryMethod
self.getId())
ValueError: Product factory for MyTypeOne was invalid

So, my product factory is invalid. But in which way; how should it look like?

In my profile/default/, I have a factorytool.xml:

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

types.xml:

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

One of them type definitions, types/MyTypeOne.xml:

<?xml version="1.0"?>
<object name="MyTypeOne"
        meta_type="Factory-based Type Information with dynamic views"
        xmlns:i18n="http://xml.zope.org/namespaces/i18n">
 <property name="title">MyTypeOne</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">MyTypeOne</property>
 <property name="product">MyCompany.MyPackage</property>
 <property name="factory">addMyTypeOne</property>
 <property name="immediate_view">mytypeone_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">mytypeone_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>

This should be pretty default; I'm still in the beginning, and of course like to be able to see my content objects before continuing to implement futher behaviour.

Base __init__.py, largely like created by paster create -t archetype example.archetype (taken from this old reference manual which, alas! contains some now-broken links):

"""Init and utils."""
from zope.i18nmessageid import MessageFactory
from Products.CMFCore import DirectoryView
from Products.CMFCore import utils as cmfutils
DirectoryView.registerDirectory('skins', globals())

from MyCompany.MyPackage import config
from Products.Archetypes import atapi
from Products.CMFCore import utils

archetypeMessageFactory = MessageFactory(config.PROJECTNAME)

def initialize(context):
    """Initializer called when used as a Zope 2 product.
    ...
    """
    content_types, constructors, ftis = atapi.process_types(
        atapi.listTypes(config.PROJECTNAME),
        config.PROJECTNAME)
    
    for atype, constructor in zip(content_types, constructors):
        utils.ContentInit('%s: %s' % (config.PROJECTNAME, atype.portal_type),
            content_types=(atype, ),
            permission=config.ADD_CONTENT_PERMISSIONS[atype.portal_type],
            extra_constructors=(constructor,),
            ).initialize(context)

What can I do to find and/or fix the problem?
Any additional information needed?

Thank you!

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?

  • 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)''

I created a question on StackOverflow as well; I'll take care of syncing important informations or solutions.

How about submitting your live codes at GitHub so that the context might be more clear? For example, https://github.com/l34marr/crgis.atcontents/tree/plone4 is my custom Archetypes package that you might see if working.

Done; see https://github.com/tobiasherp/MyCompany.MyProduct. If I find the time, I'll create a doctest like the one in your package.

I must confess that my custom Archetypes packages are all created with zopeskel, by the time it worked like http://docs.plone.org/4/en/develop/addons/helloworld/extend/addon.html advertised. I do not find the step-by-step docs for mr.bob to create a simplest Archetypes package, so here is how I just work with a vanilla Plone 4.3.12 instance:

First, install ZopeSkel 2.21.2 (not 3.x), update in your buildout.cfg or develop.cfg

parts =
   ...
   zopeskel

[zopeskel]
# installs paster and Zopeskel
recipe = zc.recipe.egg
eggs =
   PasteScript
   ZopeSkel

Then pin ZopeSkel to version 2.21.2 (say, in version.cfg or buildout.cfg). Run buildout and you should see zopeskel and paster in bin folder.

$ cd src
$ ../bin/zopeskel archetype MyCompany.MyProduct

archetype: A Plone project that uses Archetypes content types

This creates a Plone project that uses Archetypes content types.
It has local commands that will allow you to add content types
and to add fields to your new content types.


If at any point, you need additional help for a question, you can enter
'?' and press RETURN.

Expert Mode? (What question mode would you like? (easy/expert/all)?) ['easy']:
...

Develop the package with buildout. Then create the Archetypes type with paster. See http://docs.plone.org/4/en/develop/addons/helloworld/extend/content.html

$ cd MyCompany.MyProduct
$ ../../bin/paster addcontent contenttype
Enter contenttype_name (Content type name ) ['Example Type']: MyType
Enter contenttype_description (Content type description ) ['Description of the Example Type']:
Enter folderish (True/False: Content type is Folderish ) [False]:
Enter global_allow (True/False: Globally addable ) [True]:
Enter allow_discussion (True/False: Allow discussion ) [False]:

Finally, you will see MyType from the Add new ... menu.

I believe there's a good reason to deprecate paster and zopeskel. However, the existing docs I could find is to utilize ZopeSkel. And I also believe you can directly adapt Dexterity types to meet your needs. Consider migrating your Archetypes items to Dexterity. Good luck.

I come from the future and you will thank this advice later: stop using Archetypes for new developments now; Dexterity has been with us for many years and is perfectly fine to mix content types frameworks on a Plone 4.3 site. I do it all the time and I've been doing it since 2011 with no major issues.

I guess you have spend more time debugging now that the time you'll have to invest to learn Dexterity:

https://docs.plone.org/external/plone.app.dexterity/docs/

Right; I'll go for Dexterity now.
However, there has been a solution for my problem. To put it short:

In configure.zcml:

New content/configure.zcml:

<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>>

... and finally fixed the syntax error (the class statement doesn't accept argument tuples).