[Zope-CMF] Re: Historical revisions in CMF

Terry Kerr terry@adroit.net
Thu, 27 Mar 2003 17:35:28 +1100


I have added the Historian base class to PortalTypes which adds the History 
mechanism to all the item types in the portal.    The problem with this related 
to workflow states is that the workflow history itself is actually a 
PersistantMapping, ie, and object with its own history.  So you cannot rely on 
standard approaches such as protal_worflow.getInfoFor('review_state') when 
looping through the ob.manage_change_history() to find the most recent 
'published' state of the item.  In fact, the workflow persistance mapping will 
be the same (in its current state) for each version!  This is demonstrated by 
simply visiting the History tab of an object in a workflow and looking at its 
state in each revision...they are all the same!

So the method I cam up with does what you suggested and simply looks at the 
workflow history of the current history version, finds the last published 
version, then compares its time with the time of all versions in the object 
history to find the correct one to display.  My concern is that times will not 
always align exactly...but I am not sure about this.

I created an external method in the root of my CMF instance with the method:

def getPublishedRevision(self, ob):
     # first find the correct revision using the workflow history of the
     # object
     workflow_history = list(ob.workflow_history['news_workflow'])
     workflow_history.reverse()
     for state in workflow_history:
         time = state['time']
         if state['review_state'] == 'published':
             break
     # now loop through history of real objects to get the correct one
     for item in ob.manage_change_history():
         if long(item['time']) == long(time) :
             return self.HistoricalRevisions[item['key']]
     return ob

A quick test proved that this worked in my case.  A fair few other changes have 
to be made to the template obviously to make all this work.

terry


> 
> I've enabled CMF to handle revisions by allowing it to inherit from
> OFS.History, on a experimental basis, and it works fine so far. If you want
> to try it, open CMFCore/PortalContent.py with any editor an perform the
> changes indicated down below. After you restart Zope, the "History" tab will
> appear for all contentish objects, in the management interface. Starting
> that point you'll need to provide methods (or modify existing ones) to
> access those revisions. I'm including a simple history-viewer script.
> 
> A simple and general workaround in your case is to modify the view methods
> of your content types to make them render the closest published revision (or
> any other you indicate, based on your site's policy), when the object's
> state is 'retracted' (yes, create that one). As currently there's no
> relation between revisions and the workflow's review_history, as provided by
> 'portal_workflow.getInfoFor', one of your to-write methods might be one that
> compares timestamps and returns the mentioned revision object.
> 
> I'll publish a How-to on this subject, provided there's no code conflicts
> I'm not aware of. :)
> 
> 
> 
> Ausum
> 
> 
> 
> 
> Modifications to PortalContent.py:
> 
> ....................
>     NoWL = 0
> except ImportError:
>     NoWL = 1
> 
> from OFS.History import Historical        # added line
> 
> class PortalContent(DynamicType, Historical, CMFCatalogAware, SimpleItem):
> # added 'Historical'
> 
>     """
>         Base class for portal objects.
> 
>         Provides hooks for reviewing, indexing, and CMF UI.
> .......
> 
> and:
> .........
>                      + CMFCatalogAware.manage_options
>                      + SimpleItem.manage_options
>                      + Historical.manage_options     # added line
>                      )
> 
>     security = ClassSecurityInfo()
> .......
> 
> A basic python script to view the history information of any contentish
> object:
> 
> # HistoryWatcher:
> for item in context.manage_change_history():
>     print
>     for k,v in item.items():
>         print k, ":", v
>     historical_object = context.HistoricalRevisions[item['key']]
>     print historical_object
> 
> return printed
> 
> 



-- 
Terry Kerr (terry@adroit.net)
Adroit Internet Solutions (www.adroit.net)
Phone: +61 3 9563 4461
Fax: +61 3 9563 3856