mirrored from git://git.moodle.org/moodle.git
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
/
formslib.php
399 lines (347 loc) · 16.1 KB
/
formslib.php
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
<?php
/**
* formslib.php - library of classes for creating forms in Moodle, based on PEAR QuickForms.
* THIS IS NOT YET PART OF THE MOODLE API, IT IS HERE FOR TESTING ONLY
* @author Jamie Pratt
* @version $Id$
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
//point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else.
if (FALSE===strstr(ini_get('include_path'), $CFG->libdir.'/pear' )){
ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
}
require_once 'HTML/QuickForm.php';
require_once 'HTML/QuickForm/DHTMLRulesTableless.php';
require_once 'HTML/QuickForm/Renderer/Tableless.php';
if ($CFG->debug >= DEBUG_ALL){
PEAR::setErrorHandling(PEAR_ERROR_PRINT);
}
class moodleform {
var $_form; // quickform object definition
var $_customdata; // globals workaround
function moodleform($action, $customdata=null, $method='post', $target='', $attributes=null) {
$form_name = rtrim(get_class($this), '_form');
$this->_customdata = $customdata;
$this->_form =& new MoodleQuickForm($form_name, $method, $action, $target, $attributes);
$this->definition();
$this->_form->addElement('hidden', 'sesskey', null); // automatic sesskey protection
$this->_form->setDefault('sesskey', sesskey());
$this->_form->addElement('hidden', '_qf__', null); // form submission marker
$this->_form->setDefault('_qf__', 1);
// we have to know all input types before processing submission ;-)
$this->_process_submission($method);
}
function _process_submission($method) {
$submission = array();
if ($method == 'post') {
if (!empty($_POST)) {
$submission = $_POST;
}
} else {
$submission = array_merge_recursive($_GET, $_POST); // emulate handling of parameters in xxxx_param()
}
// following trick is needed to enable proper sesskey checks when using GET forms
// the _qf__ serves as a marker that form was actually submitted
if (array_key_exists('_qf__', $submission) and $submission['_qf__'] == 1) {
if (!confirm_sesskey()) {
error('Incorrect sesskey submitted, form not accepted!');
}
} else {
$submission = array();
}
$this->_form->updateSubmission($submission);
}
function set_defaults($default_values, $slashed=false) {
if (is_object($default_values)) {
$default_values = (array)$default_values;
}
$filter = $slashed ? 'stripslashes' : NULL;
$this->_form->setDefaults($default_values, $filter);
}
function is_submitted() {
return $this->_form->isSubmitted();
}
function is_validated() {
static $validated = null;
if ($validated === null) {
$internal_val = $this->_form->validate();
$moodle_val = $this->validation($this->_form->exportValues(null, true));
if ($moodle_val !== true) {
if (!empty($moodle_val)) {
foreach ($moodle_val as $element=>$msg) {
$this->_form->setElementError($element, $msg);
}
}
$moodle_val = false;
}
$validated = ($internal_val and $moodle_val);
}
return $validated;
}
function data_submitted($slashed=true) {
if ($this->is_submitted() and $this->is_validated()) {
$data = $this->_form->exportValues(null, $slashed);
if (empty($data)) {
return NULL;
} else {
return (object)$data;
}
} else {
return NULL;
}
}
function display() {
$this->_form->display();
}
// abstract method - always override
function definition() {
error('Abstract form_definition() method in class '.get_class($this).' must be overriden, please fix the code.');
}
// dummy stub method - override if needed
function validation($data) {
// return array of errors ("fieldname"=>"error message") or true if ok
return true;
}
}
class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
var $_types = array();
/**
* Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless
* @param string $formName Form's name.
* @param string $method (optional)Form's method defaults to 'POST'
* @param string $action (optional)Form's action
* @param string $target (optional)Form's target defaults to none
* @param mixed $attributes (optional)Extra attributes for <form> tag
* @param bool $trackSubmit (optional)Whether to track if the form was submitted by adding a special hidden field
* @access public
*/
function MoodleQuickForm($formName, $method, $action, $target='', $attributes=null){
global $CFG;
HTML_Common::HTML_Common($attributes);
$target = empty($target) ? array() : array('target' => $target);
//no 'name' atttribute for form in xhtml strict :
$attributes = array('action'=>$action, 'method'=>$method, 'id'=>$formName) + $target;
$this->updateAttributes($attributes);
//this is custom stuff for Moodle :
$oldclass= $this->getAttribute('class');
if (!empty($oldclass)){
$this->updateAttributes(array('class'=>$oldclass.' mform'));
}else {
$this->updateAttributes(array('class'=>'mform'));
}
$this->_helpImageURL="$CFG->wwwroot/lib/form/req.gif";
$this->_reqHTML =
helpbutton('requiredelement', get_string('requiredelement', 'form'),'moodle',
true, false, '', true, '<img alt="'.get_string('requiredelement', 'form').'" src="'.
$this->_helpImageURL.'" />');
$this->setRequiredNote(get_string('denotesreq', 'form', $this->getReqHTML()));
}
function setType($elementname, $paramtype) {
$this->_types[$elementname] = $paramtype;
}
function setTypes($paramtypes) {
$this->_types = $paramtypes + $this->_types;
}
function updateSubmission($submission) {
if (empty($submission)) {
$this->_submitValues = array();
$this->_flagSubmitted = false;
} else {
foreach ($submission as $key=>$s) {
if (array_key_exists($key, $this->_types)) {
$submission[$key] = clean_param($s, $this->_types[$key]);
}
}
$this->_submitValues = $this->_recursiveFilter('stripslashes', $submission);
$this->_flagSubmitted = true;
}
// need to tell all elements that they need to update their value attribute.
foreach (array_keys($this->_elements) as $key) {
$this->_elements[$key]->onQuickFormEvent('updateValue', null, $this);
}
}
function getReqHTML(){
return $this->_reqHTML;
}
/**
* Initializes a default form value
*
* @param string $elementname element name
* @param mixed $values values for that element name
* @param bool $slashed the default value is slashed
* @access public
* @return void
*/
function setDefault($elementName, $defaultValue, $slashed=false){
$filter = $slashed ? 'stripslashes' : NULL;
$this->setDefaults(array($elementName=>$defaultValue), $filter);
} // end func setDefault
/**
* Add an array of buttons to the form
* @param array $buttons An associative array representing help button to attach to
* to the form. keys of array correspond to names of elements in form.
*
* @access public
*/
function setHelpButtons($buttons, $suppresscheck=false){
foreach ($buttons as $elementname => $button){
$this->setHelpButton($elementname, $button, $suppresscheck);
}
}
/**
* Add a single button
*
* @param string $elementname name of the element to add the item to
* @param array $button - arguments to pass to setHelpButton
* @param boolean $suppresscheck - whether to throw an error if the element
* doesn't exist.
*/
function setHelpButton($elementname, $button, $suppresscheck=false){
if (array_key_exists($elementname, $this->_elementIndex)){
//_elements has a numeric index, this code accesses the elements by name
$element=&$this->_elements[$this->_elementIndex[$elementname]];
if (method_exists($element, 'setHelpButton')){
$element->setHelpButton($button);
}else{
$a=new object();
$a->name=$element->getName();
$a->classname=get_class($element);
print_error('nomethodforaddinghelpbutton', 'form', '', $a);
}
}elseif (!$suppresscheck){
print_error('nonexistentformelements', 'form', '', $elementname);
}
}
function exportValues($elementList= null, $addslashes=true){
$unfiltered=parent::exportValues($elementList);
unset($unfiltered['sesskey']); // we do not need to return sesskey
unset($unfiltered['_qf__']); // we do not need the submission marker too
if ($addslashes){
return $this->_recursiveFilter('addslashes',$unfiltered);
} else {
return $unfiltered;
}
}
}
/**
* A renderer for MoodleQuickForm that only uses XHTML and CSS and no
* table tags, extends PEAR class HTML_QuickForm_Renderer_Tableless
*
* Stylesheet is part of standard theme and should be automatically included.
*
* @author Jamie Pratt <me@jamiep.org>
* @license gpl license
*/
class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{
/**
* Element template array
* @var array
* @access private
*/
var $_elementTemplates;
// uncomment templates below and edit formslib.php for
// ol li containers for form items.
/**
* Template used when opening a hidden fieldset
* (i.e. a fieldset that is opened when there is no header element)
* @var string
* @access private
*/
var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\">";
// var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\">\n\t\t<ol>";
// /**
// * Header Template string
// * @var string
// * @access private
// */
// var $_headerTemplate =
// "\n\t\t<legend>{header}</legend>\n\t\t<ol>";
// var $_headerTemplate =
// "\n\t\t<legend>{header}</legend>\n\t\t<ol>";
/**
* Template used when closing a fieldset
* @var string
* @access private
*/
var $_closeFieldsetTemplate = "\n\t\t</fieldset>";
// var $_closeFieldsetTemplate = "\n\t\t</ol>\n\t</fieldset>";
/**
* Required Note template string
* @var string
* @access private
*/
var $_requiredNoteTemplate =
"\n\t\t<div class=\"fdescription\">{requiredNote}</div>";
function MoodleQuickForm_Renderer(){
// switch next two lines for ol li containers for form items.
// $this->_elementTemplates=array('default'=>"\n\t\t<li class=\"fitem\"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><div class=\"qfelement<!-- BEGIN error --> error<!-- END error --> {type}\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></li>");
$this->_elementTemplates=array('default'=>"\n\t\t<div class=\"fitem\"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><div class=\"felement<!-- BEGIN error --> error<!-- END error --> {type}\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></div>",
'fieldset'=>"\n\t\t<div class=\"fitem\"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><fieldset class=\"felement<!-- BEGIN error --> error<!-- END error --> {type}\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</fieldset></div>");
parent::HTML_QuickForm_Renderer_Tableless();
}
function startForm(&$form){
$this->_reqHTML=$form->getReqHTML();
$this->_elementTemplates=str_replace('{req}', $this->_reqHTML, $this->_elementTemplates);
parent::startForm($form);
}
function startGroup(&$group, $required, $error){
if (method_exists($group, 'getElementTemplateType')){
$html = $this->_elementTemplates[$group->getElementTemplateType()];
}else{
$html = $this->_elementTemplates['default'];
}
if (method_exists($group, 'getHelpButton')){
$html =str_replace('{help}', $group->getHelpButton(), $html);
}else{
$html =str_replace('{help}', '', $html);
}
$html =str_replace('{type}', 'fgroup', $html);
$this->_templates[$group->getName()]=$html;
// Fix for bug in tableless quickforms that didn't allow you to stop a
// fieldset before a group of elements.
// if the element name indicates the end of a fieldset, close the fieldset
if ( in_array($group->getName(), $this->_stopFieldsetElements)
&& $this->_fieldsetsOpen > 0
) {
$this->_html .= $this->_closeFieldsetTemplate;
$this->_fieldsetsOpen--;
}
parent::startGroup($group, $required, $error);
}
function renderElement(&$element, $required, $error){
if (method_exists($element, 'getElementTemplateType')){
$html = $this->_elementTemplates[$element->getElementTemplateType()];
}else{
$html = $this->_elementTemplates['default'];
}
$html =str_replace('{type}', 'f'.$element->getType(), $html);
if (method_exists($element, 'getHelpButton')){
$html=str_replace('{help}', $element->getHelpButton(), $html);
}else{
$html=str_replace('{help}', '', $html);
}
$this->_templates[$element->getName()]=$html;
if (!is_null($element->getAttribute('id'))) {
$id = $element->getAttribute('id');
} else {
$id = $element->getName();
}
$element->updateAttributes(array('id'=>'id_'.$id));
parent::renderElement($element, $required, $error);
}
}
$GLOBALS['_HTML_QuickForm_default_renderer']=& new MoodleQuickForm_Renderer();
MoodleQuickForm::registerElementType('checkbox', "$CFG->libdir/form/checkbox.php", 'MoodleQuickForm_checkbox');
MoodleQuickForm::registerElementType('file', "$CFG->libdir/form/file.php", 'MoodleQuickForm_file');
MoodleQuickForm::registerElementType('group', "$CFG->libdir/form/group.php", 'MoodleQuickForm_group');
MoodleQuickForm::registerElementType('password', "$CFG->libdir/form/password.php", 'MoodleQuickForm_password');
MoodleQuickForm::registerElementType('radio', "$CFG->libdir/form/radio.php", 'MoodleQuickForm_radio');
MoodleQuickForm::registerElementType('select', "$CFG->libdir/form/select.php", 'MoodleQuickForm_select');
MoodleQuickForm::registerElementType('text', "$CFG->libdir/form/text.php", 'MoodleQuickForm_text');
MoodleQuickForm::registerElementType('textarea', "$CFG->libdir/form/textarea.php", 'MoodleQuickForm_textarea');
MoodleQuickForm::registerElementType('date_selector', "$CFG->libdir/form/dateselector.php", 'MoodleQuickForm_date_selector');
MoodleQuickForm::registerElementType('date_time_selector', "$CFG->libdir/form/datetimeselector.php", 'MoodleQuickForm_date_time_selector');
MoodleQuickForm::registerElementType('htmleditor', "$CFG->libdir/form/htmleditor.php", 'MoodleQuickForm_htmleditor');
MoodleQuickForm::registerElementType('static', "$CFG->libdir/form/static.php", 'MoodleQuickForm_static');
MoodleQuickForm::registerElementType('hidden', "$CFG->libdir/form/hidden.php", 'MoodleQuickForm_hidden');
?>