[Zope-CMF] Re: Historical revisions in CMF

Ausum Studio ausum_studio@hotmail.com
Thu, 27 Mar 2003 12:47:58 -0500


Timestamps from both lists are hardly the same. For example, when you create
an object, its revision's time will be a few miliseconds later than the
status changed time, depending on your server's speed and resources use
level. Now, although the status change itself does effectively stamps a
revision, storing the path to the method that commited the transaction, I
choose to use the immediately previous to status-changed-time revision, in
order to provide:

a. A way to avoid the need to review the script again, when we write new
methods that commit changes to the status of an object. (in the case it
checks against the method name, found in the path).
b. To associate the author of the last revision to the status change, and
not the person who commit the change. (Which is already stored)

So I've come up with this script that compares the timestamps in
miliseconds, and returns an enhanced review history_list. When possible it
will add the revision information to each status changed item. (Tests
appreaciated)



Ausum



## Script (Python) "review_history_wrevisions"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=
##
review_history_list = list(context.portal_workflow.getInfoFor(context,
'review_history'))
revisions_list = context.manage_change_history()
suma = review_history_list + revisions_list

def mycomp(x,y):
    t = x['time'].millis() - y['time'].millis()
    return int(t)

suma.sort(mycomp)
suma.reverse()

newlist = []
for item in suma:
    if item.has_key('review_state'):
        newdict={}
        itemnum = suma.index(item)
        for k,v in item.items():
            newdict[k] = v
        if itemnum + 1 < len(suma):
            nli = suma[itemnum+1]
            if nli.has_key('key'):
                for k,v in nli.items():
                    newdict['version_'+ k] = v

        elif itemnum + 1 == len(suma) and item['action']=='created':
            nli = suma[itemnum-1]
            if nli.has_key('key'):
                for k,v in nli.items():
                    newdict['version_'+ k] = v
        newlist.append(newdict)
return newlist



----- Original Message -----
From: "Terry Kerr" <terry@adroit.net>
>
>
> 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
>
>
(...)