Champs client++
[Plinn.git] / ContentHistory.py
1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright © 2005-2009 Benoît PIN <benoit.pin@ensmp.fr> #
5 # #
6 # This program is free software; you can redistribute it and/or #
7 # modify it under the terms of the GNU General Public License #
8 # as published by the Free Software Foundation; either version 2 #
9 # of the License, or (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program; if not, write to the Free Software #
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #
19 #######################################################################################
20 """
21 Module to manage history of contents (comparisons, copy to present).
22
23
24
25 """
26
27 from Globals import InitializeClass
28 from AccessControl import ClassSecurityInfo
29 from ExtensionClass import Base
30 import Acquisition
31 from zope.interface import implements
32 from OFS.History import historicalRevision
33 from Products.PluginIndexes.common import safe_callable
34 from interfaces import IContentHistory
35 from Products.CMFCore.permissions import ModifyPortalContent
36 from permissions import ViewHistory
37 from struct import pack, unpack
38 from DateTime import DateTime
39
40 class ContentHistory(Base, Acquisition.Implicit) :
41 """ Utility to manage historical entries of a content
42 """
43 implements(IContentHistory)
44 security = ClassSecurityInfo()
45
46 def __init__(self, content) :
47 self._content = content
48
49 security.declareProtected(ViewHistory, 'listEntries')
50 def listEntries(self, first=0, last=20):
51 oid = self._content._p_oid
52 db = self._content._p_jar.db()
53 r = db.history(oid, size=last)
54
55 if r is None:
56 # storage doesn't support history
57 return ()
58
59 r=r[first:]
60
61 for d in r:
62 d['time']=DateTime(d['time'])
63 d['key']='.'.join(map(str, unpack(">HHHH", d['tid'])))
64
65 return r
66
67 security.declareProtected(ViewHistory, 'getHistoricalRevisionByKey')
68 def getHistoricalRevisionByKey(self, key, withContext=False):
69
70 serial = apply(pack, ('>HHHH',) + tuple(map(int, key.split('.'))))
71 content = self._content
72 rev = historicalRevision(content, serial)
73 rev = rev.__of__(content.aq_parent)
74 if withContext is False :
75 return rev, DateTime(rev._p_mtime)
76 else :
77 ctx = {}
78 if isinstance(withContext, int) :
79 first = max(withContext-1, 0)
80 entries = self.listEntries(first=first, last=withContext+2)
81
82 if len(entries) == 3 :
83 ctx['next'], ctx['current'], ctx['previous'] = entries
84 elif len(entries) == 2 :
85 serials = [e['tid'] for e in entries]
86 i = serials.index(serial)
87 if i == 0 :
88 # last (newest) transaction
89 ctx['current'], ctx['previous'] = entries
90 else :
91 ctx['next'], ctx['current'] = entries
92 elif len(entries) == 1 :
93 ctx['current'] = entries[0]
94 return rev, ctx
95
96
97 security.declareProtected(ViewHistory, 'compare')
98 def compare(self, leftkey, rightkey):
99 raise NotImplementedError
100
101
102 security.declareProtected(ModifyPortalContent, 'restore')
103 def restore(self, key):
104 raise NotImplementedError
105
106 InitializeClass(ContentHistory)