Why Plone architecture must change


I proposed a conference on this theme but it was not keeped for PloneConf2008. Here comes a short work on its, and I will hope it create a debate.

Plone is born with a goal: make Zope 2 and CMF simple. Those two are frameworks and allowed you to create a website… a so rustic website. With Plone you only needed to fill one form to have a cool site ready to use and to custom. At that time Plone was CMFPlone, an other implementation of CMFDefault.

Some new products were inserted in the bundle like GroupUserFolder in a such way that they cannot be separated from the base implementation of Plone.

The second step was the Archetypes framework: a new manner to manage object’s attributes as schema. With all informations stored in the schema,  mutators and accessors are generated on boot time and forms are generated from schema’s widgets. It was cool, but not perfect. Then the product ATcontentTypes was created to be the glue to upgrade CMFPlone as Plone: all base types from CMF are now overloaded by a type from ATContentTypes.

So came Zope 3 and Five. Five is the glue that allows Zope 2 developpers to use component architecture from Zope 3 in their code. Plone 2.5 and Plone 3 are using Five.

Another product came from Zope ‘renegades’: PluggableAuthService and its implementation in Plone: PlonePAS. It should replace the old GroupUserFolder but users and groups management templates were never refactored.

Plone 3 introduces new component in plone.app to our greatest happiness.

What part of Plone needs CMF?
Why Plone needs to know about Archetypes storage and CMFEditions strategy?
Why GroupUserFolder is always in the bundle as PlonePAS fit is API?

Now Plone is like the linux kernel: a big monolithic Plone with a lot of modules that create a base Plone 3 site. And so much glue! GroupUserFolder is always here because nobody knows and wants to work on the portal_group replacement.
If you are following Plone4Artist or PloneGov you can see that a part of these projects needs to overload Plone base configuration.

CPS 3, an other CMF-based CMS, was conceived with the thinking that components need to be independant to be reusable and maintainable:

  • CPSSchema depends only on Zope
  • CPSCore depends only on Zope
  • CPSDocument depends only on CPSSchema
  • CPSDefault depends on CPSCore and CPSSchema, and implements the CPS site.

After 2 years it was divided into platforms:

  • CPS Legacy
  • CPS Courier
  • CPS Groupware

In front of that Plone propose at single product with a lot of glue that depends on others products or components that use their own glue and so on…
There’s no plone.core and plone.default and we cannot create a plone.artistsite or a plone.govsite.
Do you think that everyone need an openid or an ldap integration in Plone ?

Plone 4 must be a reimplementation, not only a new glue with new concepts. I don’t want any new functionality in Plone 4, I want modularity and scalability.

How to hide a column in CPS with CPSSkins


Since few weeks I went back in CPS to make maintenance on it. I was a CPS core developper, three years ago…
I’m customing a CPS theme with CPSSkins. It could be a very cool product if a documentation exists.
It was so in advanced on web2.0 that only few people really used it outside its main developper and Nuxeo team.

It’s the first article on CPS and not the last one.

a quick recipe to explain how to hide a skin in a part of your site

The goal is to hide the right column when the ‘projects_results’ template is used

  1. login with site Manager rights
  2. in the portal box cloick on ‘Edit themes’
  3. duplicate ‘Fille’ page and named it ‘SansColonne’
  4. switch to layout mode
  5. set column number to 1 in the main block
  6. go in the ZMI on the site root and edit the .cpsskins_theme script with the following code
theme_id = 'mysitetheme'

if REQUEST is None:
    REQUEST = context.REQUEST

if not context.portal_membership.isAnonymousUser():
    return '%s+Authenticated' % theme_id
elif REQUEST.get('PUBLISHED').getId() == 'index_html':
    return '%s+HomePage' % theme_id
elif REQUEST.get('URL').endswith('projects_results'):
    return '%s+SansColonne' % theme_id
else:
    return '%s+Fille' % theme_id