Per Erik Strandberg /cv /kurser /blog

Sometimes a third party product is almost exacly what you want to use. But sometimes it has some features that you do not want and you get annoyed and do not really know how to proceed. One option is to make a copy of the product and rewrite it. But doing this will put you in a maintenance nightmare since all updates of the original product will be hard of not impossible to insert into your version of it. One solution and/or best practice is inheritance.

As you may remember this is what it looked like when we created an instance of my message before this little tutorial (do not get confused over the use of Swedish in the screen shot - somehow the browser I used was set on Swedish at the time of my screenshots):
http://www.pererikstrandberg.se/blog/plone/my_inherited_message_1_old.png

The inheritance trick

By inheriting the product into a product controlled by you you can do minor modifications and still be able to allow the original product to upgrade (hopefully only with minor problems).

I will illustrate this principle by overriding an old version of my message (the Plone Archetypes View Template Modifications version) into a product I call MyInheritedMessage. This will include the usual set of files or even more - but they are almost empty. Also your average product contains dozens of files and usually this approach only require about the same amount of files. Also the total number of lines of code is less than 100 in the inherited product (counting blank lines and comments).

__init__.py
config.py
configure.zcml
message.py
Extensions/Install.py
profiles/default/types/MyMessage.xml

In order for the framework to see the different products as one content type there will be inheritance also the behavior I want to change is the default values of the fields in the my message content type. So some important code is stored in message.py:

from Products.Archetypes.atapi import *
from Products.MyMessage.message import MyMessage as MotherMessage
from Products.MyMessage.message import schema as MotherSchema
from Products.MyInheritedMessage.config import PROJECTNAME

schema = MotherSchema.copy()
schema['title'].default='Untitled'
schema['alpha'].default='42'
schema['bravo'].default='1337'
schema['charlie'].default='-713'

class MyMessage(MotherMessage):
    schema = schema

registerType(MyMessage, PROJECTNAME)

As you can see I:

Overriding the old my message

Four lines of xml will make this new product override the old my message and force plone into using the inherited one. These are stored in profiles/default/types/MyMessage.xml:

<?xml version="1.0"?>
<object name="MyMessage">
 <property name="product">MyInheritedMessage</property>
</object>

These lines will be activated when the product my inherited message is installed. Most likely you will need to have the product my message installed prior to that - but I have not tried what happens otherwise. So this is what it should look like when you install the new product.
http://www.pererikstrandberg.se/blog/plone/my_inherited_message_2_override.png

As you might have guessed our content type called my message is now replaced with a new content type called, you guessed it: my message. So how does one know that we are using the new one? Well we just have to try it to see it. That is why you should introduce a little something to separate your products - even if it is just a new default value.
http://www.pererikstrandberg.se/blog/plone/my_inherited_message_3_same_content_type.png

The final result

As you might have guessed any new instances of my message will have the properties defined in the old my message product, and also any behavior defined in my inherited message. In case of conflicts the new features will override the old - just like we wanted.
http://www.pererikstrandberg.se/blog/plone/my_inherited_message_4_default_values.png

Download link

Download here [1]


See also Plone Cms.
This page belongs in Kategori Programmering.