comparison data/plugin/action/submitbase.py @ 622:12465aa315be

add code from ActionMarket/FormSubmit (form_submit-1.7.tar.gz) - outdated code for moin 1.7/1.8
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Mon, 25 Mar 2013 17:09:15 +0100
parents
children 5f499a634857
comparison
equal deleted inserted replaced
621:a8d1eb833705 622:12465aa315be
1 # -*- coding: iso-8859-1 -*-
2
3 """
4 MoinMoin - submitbase Action
5
6 All actions handling forms should extend SubmitBase class.
7
8 Basic methods to override:
9 - validate
10 - sanitize
11 - submit
12
13 Base class methods should be called at first from overriding methods.
14 All data sent from user are filtered by _exlude_metadata() and then stored in
15 fields dictionary. Data are then sorted into labels and values lists.
16
17 @copyright: 2008 by Peter Bodi <petrdll@centrum.sk>
18 @license: GNU GPL, see COPYING for details.
19 """
20
21 import os, sys, copy, codecs
22
23 from MoinMoin import wikiutil
24 from MoinMoin.action import ActionBase
25 from MoinMoin.Page import Page
26 from MoinMoin.action import AttachFile
27 from MoinMoin.action import getHandler
28 from MoinMoin.security.textcha import TextCha
29
30 def execute(pagename, request):
31 raise NotImplementedError
32
33 class SubmitBase(ActionBase):
34 """ submit base class with some generic stuff to inherit """
35
36 debug = True
37 msgtype = 'text/html'
38
39 metadata = [
40 'doit',
41 'action',
42 'actions[]',
43 'labels',
44 'targetfile',
45 'targetpage',
46 'targetemail',
47 'file',
48 'file__filename__',
49 'uploadlabel',
50 'textcha-question',
51 'textcha-answer'
52 ]
53
54 def __init__(self, pagename, request):
55 ActionBase.__init__(self, pagename, request)
56
57 self.msg = ""
58 self.actions = []
59 self.fields = {}
60 self.labels = []
61 self.values = []
62 self.attachFile = ""
63 self.attachContent = ""
64 self.targetpage = self.pagename
65 self.module = self.__module__.split(".").pop()
66
67 if self.request.form.has_key("actions[]"):
68 self.actions = copy.copy(self.request.form.get("actions[]"))
69 else:
70 self.actions.append(self.module)
71
72 self.fields = self._exclude_metadata(self.request.form)
73
74 # file upload is present
75 if request.form.has_key("file"):
76 self.attachFile = request.form.get("file__filename__")
77 self.attachContent = request.form.get("file")[0]
78 self.attachLabel = request.form.get("uploadlabel")[0]
79 self.attachLabel = self.attachLabel.encode('utf-8')
80
81 # page where all submited data will be stored
82 if request.form.has_key("targetpage"):
83 targetpage = request.form.get("targetpage")[0]
84 page = Page(self.request, targetpage)
85 if page.isStandardPage(False):
86 self.targetpage = targetpage
87
88 def is_last(self):
89 """ Evaluates whether currently executed action is last action from actions array
90 """
91 module = self.module
92 lastAction = self.actions.pop()
93
94 if module == lastAction:
95 return True
96 else:
97 return False
98
99 def append_link(self):
100 """ Makes formated link and apends it to fields dictionary
101 """
102 if self.attachFile:
103 attachUrl = AttachFile.getAttachUrl(self.targetpage, self.attachFile, self.request)
104 attachLink = self.request.getQualifiedURL() + attachUrl
105 self.fields[self.attachLabel] = attachLink
106 elif self.request.form.has_key("file"):
107 self.fields[self.attachLabel] = ""
108
109 def validate(self):
110 """ Validates user input.
111
112 On error raise Exception and assign error message to self.msg property
113 """
114 if not TextCha(self.request).check_answer_from_form(self.form):
115 self.msg = self._("Incorrect answer to control question")
116 raise SubmitValidationError(self.msg)
117
118 empty = True
119 for name, value in self.fields.iteritems():
120 if value:
121 empty = False
122 break
123 if empty:
124 self.msg = self._("Form is empty")
125 raise SubmitValidationError(self.msg)
126
127 def sanitize(self):
128 """ Sanitize input data passed by validation """
129 for label, value in self.fields.iteritems():
130 self.fields[label] = wikiutil.escape(value)
131
132 def submit(self):
133 """ Main submit logic
134
135 Works with validated and sanitized data
136 """
137 self.append_link()
138 self.labels, self.values = self._sort_fields(self.fields, self.request.form)
139
140 def do_action(self):
141 """ Executes core methods: validate, sanitize, submit.
142
143 Method is executed from ActionBase.render()
144 """
145 if not self.debug:
146 try:
147 self.validate()
148 self.sanitize()
149 self.submit()
150 except SubmitValidationError:
151 return False, self.msg
152 except Exception, e:
153 """ TODO: Log exception """
154 return False, e
155 else:
156 try:
157 self.validate()
158 self.sanitize()
159 self.submit()
160 except SubmitValidationError:
161 return False, self.msg
162
163
164 self.msg = self._("Data has been processed successfuly")
165
166 return True, self.msg
167
168 def do_action_finish(self, success):
169 if success:
170 if self.is_last():
171 self.render_success(self.error, self.msgtype)
172 else:
173 self.render_msg(self.error, self.msgtype)
174 if not self.is_last():
175 raise SubmitError
176
177 def render_success(self, msg, msgtype):
178 """ Triggered on success """
179 self._delete_cache()
180 ActionBase.render_success(self, msg, self.msgtype)
181
182 def render_msg(self, msg, msgtype):
183 """ Triggered on error """
184 if not msg:
185 msg = self._("Failed to process data")
186 msg = self._("Error - %s") % msg
187 self._delete_cache()
188 ActionBase.render_msg(self, msg, self.msgtype)
189
190 def _delete_cache(self):
191 """ Delete cache after each form submit """
192 pagename = self.pagename
193 request = self.request
194
195 arena = request.form.get('arena', ['Page.py'])[0]
196 if arena == 'Page.py':
197 arena = Page(request, pagename)
198 key = request.form.get('key', ['text_html'])[0]
199
200 # Remove cache entry (if exists), and send the page
201 from MoinMoin import caching
202 caching.CacheEntry(request, arena, key, scope='item').remove()
203 caching.CacheEntry(request, arena, "pagelinks", scope='item').remove()
204
205 def _exclude_metadata(self, form):
206 """ Filter all form metadata and returns only data send by user """
207 fields = copy.deepcopy(form)
208
209 for label, value in form.iteritems():
210 if self.metadata.count(label) > 0:
211 del fields[label]
212 else:
213 fields[label] = value[0]
214
215 return fields
216
217 def _sort_fields(self, fields, form):
218 """ Sort form fields to order defined in CGI labels parameter
219
220 labels is string containing field names separated by semicolon
221 Generation should be defined in FormFooter macro
222 """
223 labels = []
224 values = []
225
226 if form.has_key('labels'):
227 _labels = form.get('labels')[0].split(";")
228 for label in _labels:
229 label = label.encode('utf-8')
230 labels.append(label)
231 values.append(fields[label])
232 else:
233 labels = fields.keys();
234 values = fields.values();
235
236 return labels, values
237
238 class SubmitError(Exception):
239 """ Exception raised for submit action errors """
240
241 class SubmitValidationError(Exception):
242 """ Exception raised for errors during validation """
243