-
Notifications
You must be signed in to change notification settings - Fork 96
/
Undo.py
138 lines (112 loc) · 4.17 KB
/
Undo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Undo support.
"""
import binascii
from Acquisition import Implicit
from AccessControl import ClassSecurityInfo
from AccessControl.class_init import InitializeClass
from AccessControl.Permissions import undo_changes
from DateTime.DateTime import DateTime
import transaction
from App.Management import Tabs
from App.special_dtml import DTMLFile
class UndoSupport(Tabs, Implicit):
security = ClassSecurityInfo()
manage_options = (
{'label': 'Undo', 'action': 'manage_UndoForm'},
)
security.declareProtected(undo_changes, 'manage_UndoForm')
manage_UndoForm = DTMLFile(
'dtml/undo',
globals(),
PrincipiaUndoBatchSize=20,
first_transaction=0,
last_transaction=20,
)
def _get_request_var_or_attr(self, name, default):
if hasattr(self, 'REQUEST'):
REQUEST = self.REQUEST
if name in REQUEST:
return REQUEST[name]
if hasattr(self, name):
v = getattr(self, name)
else:
v = default
REQUEST[name] = v
return v
else:
if hasattr(self, name):
v = getattr(self, name)
else:
v = default
return v
security.declareProtected(undo_changes, 'undoable_transactions')
def undoable_transactions(self, first_transaction=None,
last_transaction=None,
PrincipiaUndoBatchSize=None):
if first_transaction is None:
first_transaction = self._get_request_var_or_attr(
'first_transaction', 0)
if PrincipiaUndoBatchSize is None:
PrincipiaUndoBatchSize = self._get_request_var_or_attr(
'PrincipiaUndoBatchSize', 20)
if last_transaction is None:
last_transaction = self._get_request_var_or_attr(
'last_transaction',
first_transaction + PrincipiaUndoBatchSize)
r = self._p_jar.db().undoInfo(first_transaction, last_transaction)
for d in r:
d['time'] = t = DateTime(d['time'])
desc = d['description']
tid = d['id']
if desc:
desc = desc.split()
d1 = desc[0]
desc = ' '.join(desc[1:])
if len(desc) > 60:
desc = desc[:56] + ' ...'
tid = "%s %s %s %s" % (encode64(tid), t, d1, desc)
else:
tid = "%s %s" % (encode64(tid), t)
d['id'] = tid
return r
security.declareProtected(undo_changes, 'manage_undo_transactions')
def manage_undo_transactions(self, transaction_info=(), REQUEST=None):
"""
"""
tids = []
descriptions = []
for tid in transaction_info:
tid = tid.split()
if tid:
tids.append(decode64(tid[0]))
descriptions.append(tid[-1])
if tids:
transaction.get().note(u"Undo %s" % ' '.join(descriptions))
self._p_jar.db().undoMultiple(tids)
if REQUEST is not None:
REQUEST.RESPONSE.redirect("%s/manage_UndoForm" % REQUEST['URL1'])
InitializeClass(UndoSupport)
# Blech, need this cause binascii.b2a_base64 is too pickly
def encode64(s, b2a=binascii.b2a_base64):
if len(s) < 58:
return b2a(s)
r = []
a = r.append
for i in range(0, len(s), 57):
a(b2a(s[i:i + 57])[:-1])
return ''.join(r)
def decode64(s, a2b=binascii.a2b_base64):
__traceback_info__ = len(s), repr(s)
return a2b(s + '\n')