1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2009 Benoît PIN <benoit.pin@ensmp.fr> #
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. #
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. #
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 #######################################################################################
21 Adapters to plug specific contentish interfaces to historycal interface.
27 from Globals
import InitializeClass
28 from AccessControl
import ClassSecurityInfo
29 from Products
.CMFCore
.permissions
import ModifyPortalContent
30 from permissions
import ViewHistory
31 from difflib
import SequenceMatcher
32 from ContentHistory
import ContentHistory
33 from types
import UnicodeType
34 from htmlentitydefs
import name2codepoint
35 from cgi
import escape
38 rent
= re
.compile(r
"&(?P<entName>[A-Za-z]+);")
40 class DocumentHistory(ContentHistory
) :
42 security
= ClassSecurityInfo()
44 security
.declareProtected(ViewHistory
, 'compare')
45 def compare(self
, leftkey
, rightkey
):
46 leftRev
, leftDate
= self
.getHistoricalRevisionByKey(leftkey
)
47 rightRev
, rightDate
= self
.getHistoricalRevisionByKey(rightkey
)
49 left
= leftRev
.EditableBody()
50 right
= rightRev
.EditableBody()
52 infos
= {'diff' : html_ready_diff(left
, right
)
53 ,'leftDate' : leftDate
54 ,'rightDate' : rightDate
58 security
.declareProtected(ModifyPortalContent
, 'restore')
59 def restore(self
, key
):
60 rev
= self
.getHistoricalRevisionByKey(key
)[0]
61 self
._content
.edit(rev
.Format(), rev
.EditableBody())
64 InitializeClass(DocumentHistory
)
66 class FolderishHistory(ContentHistory
) :
68 security
= ClassSecurityInfo()
70 security
.declareProtected(ViewHistory
, 'compare')
71 def compare(self
, leftkey
, rightkey
):
72 leftRev
, leftDate
= self
.getHistoricalRevisionByKey(leftkey
)
73 rightRev
, rightDate
= self
.getHistoricalRevisionByKey(rightkey
)
75 leftIds
= leftRev
.objectIds()
78 title
= leftRev
[id].Title()
80 leftTitleAndIds
.append('%s (%s)' % (id, title
))
82 leftTitleAndIds
.append('%s' % id)
83 left
= '\n'.join(leftTitleAndIds
)
85 rightIds
= rightRev
.objectIds()
88 title
= rightRev
[id].Title()
90 rightTitleAndIds
.append('%s (%s)' % (id, title
))
92 rightTitleAndIds
.append('%s' % id)
93 right
= '\n'.join(rightTitleAndIds
)
95 infos
= {'diff' : html_ready_diff(left
, right
)
96 ,'leftDate' : leftDate
97 ,'rightDate' : rightDate
102 security
.declareProtected(ModifyPortalContent
, 'restore')
103 def restore(self
, key
):
106 InitializeClass(FolderishHistory
)
111 InitializeClass(FolderishHistory
)
113 def html_ready_diff(left
, right
, n
=3) :
114 if isinstance(left
, UnicodeType
) :
115 left
= left
.encode('utf-8')
116 if isinstance(right
, UnicodeType
) :
117 right
= right
.encode('utf-8')
118 left
= rent
.sub(convertEnt
, left
)
119 right
= rent
.sub(convertEnt
, right
)
120 sm
= SequenceMatcher()
121 leftLines
= left
.splitlines()
122 rightLines
= right
.splitlines()
123 sm
.set_seqs(leftLines
, rightLines
)
126 for i
, group
in enumerate(sm
.get_grouped_opcodes(n
)) :
129 for tag
, i1
, i2
, j1
, j2
in group
:
131 ,'left' : '\n'.join(leftLines
[i1
:i2
])
132 ,'right' : '\n'.join(rightLines
[j1
:j2
])}
137 """convert html entity to utf-8 encoded character
139 return unichr(name2codepoint
.get(m
.group('entName'), 32)).encode('utf-8')