1

I am creating a folderish type (archetype 1) and I want to have possibility to add only a single object of (archetype 2) to this folder.

Auspex
  • 2,175
  • 15
  • 35
Hare
  • 11
  • 1

4 Answers4

1

You can restrict the addable types inside your folderish type ("archetype 1") to "archetype 2" by amending the "archetypes 1" types definition (profiles/default/archetype1.xml):

<?xml version="1.0"?>
<object name="archetype1">
   ...
  <property name="filter_content_types">True</property>  
  <property name="allowed_content_types">
    <element value="archetype2" />
  </property>
  ...
</object>
tisto
  • 1,337
  • 7
  • 13
  • Sorry, but I now how restrict the addable types. My question - how can I add my type only ones. That is I add my type and thereafter it disappear from list of addable types and I can't possibility add this type anew. – Hare Jul 13 '11 at 11:04
  • Ok, then you should go with the solution Laurence suggested. – tisto Jul 13 '11 at 12:24
1

Ok, so you want your second type archetype 2 to be addable only once inside archetype 1?

I would do it in such a way that the Add New dropdown on the green edit bar only shows archetype 2 if it can be added (the other solutions here require the user to first render the add form and then be told that this is not allowed).

You need to make sure that your folderish archetype 1 subclasses ConstrainTypesMixin.

I think if you use the folderish content types in Products.ATContentTypes you will automatically subclass this mixin class, but it helps to make sure.

Then, inside archetype 1, add the method: getLocallyAllowedTypes. This method is declared in the ConstrainTypesMixin class in Products/ATContentTypes/lib/constraintypes.py

In this method you can now add the logic to check if an instance of archetype 2 has already been added. If it has, don't return it as one of the locally allowed types. If it hasn't, then return it (with the other types if they exist).

Make sure to first call super() in this method to get the locally added types from the superclass's method.

To understand how this works, you can look at the *_addableTypesInContext* method in the FactoriesSubMenuItem class in plone/app/contentmenu/menu.py to see when and how this getLocallyAllowedTypes method is called.

JC Brand
  • 2,652
  • 18
  • 18
0

You are probably best off creating a custom add form (perhaps using z3c.form) and making the placing the restriction there.

Laurence Rowe
  • 2,909
  • 17
  • 20
  • You can allow/prevent the user to create a new object of *archetype 2* in the folder by using the "Add new" dropdown menu in the green edit bar. This prevents you from first having to load the add form and then be informed that you can't create another instance. – JC Brand Jul 14 '11 at 09:58
0

You can override the createObject.cpy script and add a check there:

this_type = REQUEST.form.get('type_name') 
if this_type == 'MyATContentType':
    # MyATContentType needs a special check
    ctool = getToolByName(context, 'portal_catalog')
    this_path = '/'.join(context.getPhysicalPath())

    # Query the Catalog to see we already have an instance of this object here
    results = ctool.searchResults({'portal_type': this_type, 'path': this_path})

    if results:
        context.plone_utils.addPortalMessage(_(
            u'Sorry, but there already is an object of type %s here.' % this_type
        ))

        # Redirect to the edit form of the first found object.
        cv = results[0]
        cv_path = cv.getPath()
        return context.REQUEST.RESPONSE.redirect(cv_path + "/edit")

Provide the customized script, together with the associated .metadata file, in the skins/templates folder of your product.

Bonus tip: In Dexterity, you would add this check in dexterity.AddForm.update()

Rigel Di Scala
  • 3,150
  • 2
  • 17
  • 23