|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00040 defined('MOODLE_INTERNAL') || die(); 00041 00043 require_once 'HTML/QuickForm.php'; 00044 require_once 'HTML/QuickForm/DHTMLRulesTableless.php'; 00045 require_once 'HTML/QuickForm/Renderer/Tableless.php'; 00046 require_once 'HTML/QuickForm/Rule.php'; 00047 00048 require_once $CFG->libdir.'/filelib.php'; 00049 00050 define('EDITOR_UNLIMITED_FILES', -1); 00051 00057 function pear_handle_error($error){ 00058 echo '<strong>'.$error->GetMessage().'</strong> '.$error->getUserInfo(); 00059 echo '<br /> <strong>Backtrace </strong>:'; 00060 print_object($error->backtrace); 00061 } 00062 00063 if (!empty($CFG->debug) and $CFG->debug >= DEBUG_ALL){ 00064 PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'pear_handle_error'); 00065 } 00066 00072 function form_init_date_js() { 00073 global $PAGE; 00074 static $done = false; 00075 if (!$done) { 00076 $module = 'moodle-form-dateselector'; 00077 $function = 'M.form.dateselector.init_date_selectors'; 00078 $config = array(array('firstdayofweek'=>get_string('firstdayofweek', 'langconfig'))); 00079 $PAGE->requires->yui_module($module, $function, $config); 00080 $done = true; 00081 } 00082 } 00083 00095 abstract class moodleform { 00097 protected $_formname; // form name 00103 protected $_form; 00109 protected $_customdata; 00114 protected $_definition_finalized = false; 00115 00141 function moodleform($action=null, $customdata=null, $method='post', $target='', $attributes=null, $editable=true) { 00142 global $CFG; 00143 if (empty($CFG->xmlstrictheaders)) { 00144 // no standard mform in moodle should allow autocomplete with the exception of user signup 00145 // this is valid attribute in html5, sorry, we have to ignore validation errors in legacy xhtml 1.0 00146 if (empty($attributes)) { 00147 $attributes = array('autocomplete'=>'off'); 00148 } else if (is_array($attributes)) { 00149 $attributes['autocomplete'] = 'off'; 00150 } else { 00151 if (strpos($attributes, 'autocomplete') === false) { 00152 $attributes .= ' autocomplete="off" '; 00153 } 00154 } 00155 } 00156 00157 if (empty($action)){ 00158 $action = strip_querystring(qualified_me()); 00159 } 00160 // Assign custom data first, so that get_form_identifier can use it. 00161 $this->_customdata = $customdata; 00162 $this->_formname = $this->get_form_identifier(); 00163 00164 $this->_form = new MoodleQuickForm($this->_formname, $method, $action, $target, $attributes); 00165 if (!$editable){ 00166 $this->_form->hardFreeze(); 00167 } 00168 00169 $this->definition(); 00170 00171 $this->_form->addElement('hidden', 'sesskey', null); // automatic sesskey protection 00172 $this->_form->setType('sesskey', PARAM_RAW); 00173 $this->_form->setDefault('sesskey', sesskey()); 00174 $this->_form->addElement('hidden', '_qf__'.$this->_formname, null); // form submission marker 00175 $this->_form->setType('_qf__'.$this->_formname, PARAM_RAW); 00176 $this->_form->setDefault('_qf__'.$this->_formname, 1); 00177 $this->_form->_setDefaultRuleMessages(); 00178 00179 // we have to know all input types before processing submission ;-) 00180 $this->_process_submission($method); 00181 } 00182 00191 protected function get_form_identifier() { 00192 return get_class($this); 00193 } 00194 00204 function focus($name=NULL) { 00205 $form =& $this->_form; 00206 $elkeys = array_keys($form->_elementIndex); 00207 $error = false; 00208 if (isset($form->_errors) && 0 != count($form->_errors)){ 00209 $errorkeys = array_keys($form->_errors); 00210 $elkeys = array_intersect($elkeys, $errorkeys); 00211 $error = true; 00212 } 00213 00214 if ($error or empty($name)) { 00215 $names = array(); 00216 while (empty($names) and !empty($elkeys)) { 00217 $el = array_shift($elkeys); 00218 $names = $form->_getElNamesRecursive($el); 00219 } 00220 if (!empty($names)) { 00221 $name = array_shift($names); 00222 } 00223 } 00224 00225 $focus = ''; 00226 if (!empty($name)) { 00227 $focus = 'forms[\''.$form->getAttribute('id').'\'].elements[\''.$name.'\']'; 00228 } 00229 00230 return $focus; 00231 } 00232 00239 function _process_submission($method) { 00240 $submission = array(); 00241 if ($method == 'post') { 00242 if (!empty($_POST)) { 00243 $submission = $_POST; 00244 } 00245 } else { 00246 $submission = array_merge_recursive($_GET, $_POST); // emulate handling of parameters in xxxx_param() 00247 } 00248 00249 // following trick is needed to enable proper sesskey checks when using GET forms 00250 // the _qf__.$this->_formname serves as a marker that form was actually submitted 00251 if (array_key_exists('_qf__'.$this->_formname, $submission) and $submission['_qf__'.$this->_formname] == 1) { 00252 if (!confirm_sesskey()) { 00253 print_error('invalidsesskey'); 00254 } 00255 $files = $_FILES; 00256 } else { 00257 $submission = array(); 00258 $files = array(); 00259 } 00260 00261 $this->_form->updateSubmission($submission, $files); 00262 } 00263 00273 function _validate_files(&$files) { 00274 global $CFG, $COURSE; 00275 00276 $files = array(); 00277 00278 if (empty($_FILES)) { 00279 // we do not need to do any checks because no files were submitted 00280 // note: server side rules do not work for files - use custom verification in validate() instead 00281 return true; 00282 } 00283 00284 $errors = array(); 00285 $filenames = array(); 00286 00287 // now check that we really want each file 00288 foreach ($_FILES as $elname=>$file) { 00289 $required = $this->_form->isElementRequired($elname); 00290 00291 if ($file['error'] == 4 and $file['size'] == 0) { 00292 if ($required) { 00293 $errors[$elname] = get_string('required'); 00294 } 00295 unset($_FILES[$elname]); 00296 continue; 00297 } 00298 00299 if (!empty($file['error'])) { 00300 $errors[$elname] = file_get_upload_error($file['error']); 00301 unset($_FILES[$elname]); 00302 continue; 00303 } 00304 00305 if (!is_uploaded_file($file['tmp_name'])) { 00306 // TODO: improve error message 00307 $errors[$elname] = get_string('error'); 00308 unset($_FILES[$elname]); 00309 continue; 00310 } 00311 00312 if (!$this->_form->elementExists($elname) or !$this->_form->getElementType($elname)=='file') { 00313 // hmm, this file was not requested 00314 unset($_FILES[$elname]); 00315 continue; 00316 } 00317 00318 /* 00319 // TODO: rethink the file scanning MDL-19380 00320 if ($CFG->runclamonupload) { 00321 if (!clam_scan_moodle_file($_FILES[$elname], $COURSE)) { 00322 $errors[$elname] = $_FILES[$elname]['uploadlog']; 00323 unset($_FILES[$elname]); 00324 continue; 00325 } 00326 } 00327 */ 00328 $filename = clean_param($_FILES[$elname]['name'], PARAM_FILE); 00329 if ($filename === '') { 00330 // TODO: improve error message - wrong chars 00331 $errors[$elname] = get_string('error'); 00332 unset($_FILES[$elname]); 00333 continue; 00334 } 00335 if (in_array($filename, $filenames)) { 00336 // TODO: improve error message - duplicate name 00337 $errors[$elname] = get_string('error'); 00338 unset($_FILES[$elname]); 00339 continue; 00340 } 00341 $filenames[] = $filename; 00342 $_FILES[$elname]['name'] = $filename; 00343 00344 $files[$elname] = $_FILES[$elname]['tmp_name']; 00345 } 00346 00347 // return errors if found 00348 if (count($errors) == 0){ 00349 return true; 00350 00351 } else { 00352 $files = array(); 00353 return $errors; 00354 } 00355 } 00356 00363 protected function validate_draft_files() { 00364 global $USER; 00365 $mform =& $this->_form; 00366 00367 $errors = array(); 00368 //Go through all the required elements and make sure you hit filepicker or 00369 //filemanager element. 00370 foreach ($mform->_rules as $elementname => $rules) { 00371 $elementtype = $mform->getElementType($elementname); 00372 //If element is of type filepicker then do validation 00373 if (($elementtype == 'filepicker') || ($elementtype == 'filemanager')){ 00374 //Check if rule defined is required rule 00375 foreach ($rules as $rule) { 00376 if ($rule['type'] == 'required') { 00377 $draftid = (int)$mform->getSubmitValue($elementname); 00378 $fs = get_file_storage(); 00379 $context = get_context_instance(CONTEXT_USER, $USER->id); 00380 if (!$files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false)) { 00381 $errors[$elementname] = $rule['message']; 00382 } 00383 } 00384 } 00385 } 00386 } 00387 if (empty($errors)) { 00388 return true; 00389 } else { 00390 return $errors; 00391 } 00392 } 00393 00403 function set_data($default_values) { 00404 if (is_object($default_values)) { 00405 $default_values = (array)$default_values; 00406 } 00407 $this->_form->setDefaults($default_values); 00408 } 00409 00413 function set_upload_manager($um=false) { 00414 debugging('Old file uploads can not be used any more, please use new filepicker element'); 00415 } 00416 00422 function is_submitted() { 00423 return $this->_form->isSubmitted(); 00424 } 00425 00429 function no_submit_button_pressed(){ 00430 static $nosubmit = null; // one check is enough 00431 if (!is_null($nosubmit)){ 00432 return $nosubmit; 00433 } 00434 $mform =& $this->_form; 00435 $nosubmit = false; 00436 if (!$this->is_submitted()){ 00437 return false; 00438 } 00439 foreach ($mform->_noSubmitButtons as $nosubmitbutton){ 00440 if (optional_param($nosubmitbutton, 0, PARAM_RAW)){ 00441 $nosubmit = true; 00442 break; 00443 } 00444 } 00445 return $nosubmit; 00446 } 00447 00448 00456 function is_validated() { 00457 //finalize the form definition before any processing 00458 if (!$this->_definition_finalized) { 00459 $this->_definition_finalized = true; 00460 $this->definition_after_data(); 00461 } 00462 00463 return $this->validate_defined_fields(); 00464 } 00465 00484 function validate_defined_fields($validateonnosubmit=false) { 00485 static $validated = null; // one validation is enough 00486 $mform =& $this->_form; 00487 if ($this->no_submit_button_pressed() && empty($validateonnosubmit)){ 00488 return false; 00489 } elseif ($validated === null) { 00490 $internal_val = $mform->validate(); 00491 00492 $files = array(); 00493 $file_val = $this->_validate_files($files); 00494 //check draft files for validation and flag them if required files 00495 //are not in draft area. 00496 $draftfilevalue = $this->validate_draft_files(); 00497 00498 if ($file_val !== true && $draftfilevalue !== true) { 00499 $file_val = array_merge($file_val, $draftfilevalue); 00500 } else if ($draftfilevalue !== true) { 00501 $file_val = $draftfilevalue; 00502 } //default is file_val, so no need to assign. 00503 00504 if ($file_val !== true) { 00505 if (!empty($file_val)) { 00506 foreach ($file_val as $element=>$msg) { 00507 $mform->setElementError($element, $msg); 00508 } 00509 } 00510 $file_val = false; 00511 } 00512 00513 $data = $mform->exportValues(); 00514 $moodle_val = $this->validation($data, $files); 00515 if ((is_array($moodle_val) && count($moodle_val)!==0)) { 00516 // non-empty array means errors 00517 foreach ($moodle_val as $element=>$msg) { 00518 $mform->setElementError($element, $msg); 00519 } 00520 $moodle_val = false; 00521 00522 } else { 00523 // anything else means validation ok 00524 $moodle_val = true; 00525 } 00526 00527 $validated = ($internal_val and $moodle_val and $file_val); 00528 } 00529 return $validated; 00530 } 00531 00537 function is_cancelled(){ 00538 $mform =& $this->_form; 00539 if ($mform->isSubmitted()){ 00540 foreach ($mform->_cancelButtons as $cancelbutton){ 00541 if (optional_param($cancelbutton, 0, PARAM_RAW)){ 00542 return true; 00543 } 00544 } 00545 } 00546 return false; 00547 } 00548 00557 function get_data() { 00558 $mform =& $this->_form; 00559 00560 if (!$this->is_cancelled() and $this->is_submitted() and $this->is_validated()) { 00561 $data = $mform->exportValues(); 00562 unset($data['sesskey']); // we do not need to return sesskey 00563 unset($data['_qf__'.$this->_formname]); // we do not need the submission marker too 00564 if (empty($data)) { 00565 return NULL; 00566 } else { 00567 return (object)$data; 00568 } 00569 } else { 00570 return NULL; 00571 } 00572 } 00573 00580 function get_submitted_data() { 00581 $mform =& $this->_form; 00582 00583 if ($this->is_submitted()) { 00584 $data = $mform->exportValues(); 00585 unset($data['sesskey']); // we do not need to return sesskey 00586 unset($data['_qf__'.$this->_formname]); // we do not need the submission marker too 00587 if (empty($data)) { 00588 return NULL; 00589 } else { 00590 return (object)$data; 00591 } 00592 } else { 00593 return NULL; 00594 } 00595 } 00596 00603 function save_files($destination) { 00604 debugging('Not used anymore, please fix code! Use save_stored_file() or save_file() instead'); 00605 return false; 00606 } 00607 00615 function get_new_filename($elname=null) { 00616 global $USER; 00617 00618 if (!$this->is_submitted() or !$this->is_validated()) { 00619 return false; 00620 } 00621 00622 if (is_null($elname)) { 00623 if (empty($_FILES)) { 00624 return false; 00625 } 00626 reset($_FILES); 00627 $elname = key($_FILES); 00628 } 00629 00630 if (empty($elname)) { 00631 return false; 00632 } 00633 00634 $element = $this->_form->getElement($elname); 00635 00636 if ($element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager) { 00637 $values = $this->_form->exportValues($elname); 00638 if (empty($values[$elname])) { 00639 return false; 00640 } 00641 $draftid = $values[$elname]; 00642 $fs = get_file_storage(); 00643 $context = get_context_instance(CONTEXT_USER, $USER->id); 00644 if (!$files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false)) { 00645 return false; 00646 } 00647 $file = reset($files); 00648 return $file->get_filename(); 00649 } 00650 00651 if (!isset($_FILES[$elname])) { 00652 return false; 00653 } 00654 00655 return $_FILES[$elname]['name']; 00656 } 00657 00667 function save_file($elname, $pathname, $override=false) { 00668 global $USER; 00669 00670 if (!$this->is_submitted() or !$this->is_validated()) { 00671 return false; 00672 } 00673 if (file_exists($pathname)) { 00674 if ($override) { 00675 if (!@unlink($pathname)) { 00676 return false; 00677 } 00678 } else { 00679 return false; 00680 } 00681 } 00682 00683 $element = $this->_form->getElement($elname); 00684 00685 if ($element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager) { 00686 $values = $this->_form->exportValues($elname); 00687 if (empty($values[$elname])) { 00688 return false; 00689 } 00690 $draftid = $values[$elname]; 00691 $fs = get_file_storage(); 00692 $context = get_context_instance(CONTEXT_USER, $USER->id); 00693 if (!$files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false)) { 00694 return false; 00695 } 00696 $file = reset($files); 00697 00698 return $file->copy_content_to($pathname); 00699 00700 } else if (isset($_FILES[$elname])) { 00701 return copy($_FILES[$elname]['tmp_name'], $pathname); 00702 } 00703 00704 return false; 00705 } 00706 00713 function save_temp_file($elname) { 00714 if (!$this->get_new_filename($elname)) { 00715 return false; 00716 } 00717 if (!$dir = make_temp_directory('forms')) { 00718 return false; 00719 } 00720 if (!$tempfile = tempnam($dir, 'tempup_')) { 00721 return false; 00722 } 00723 if (!$this->save_file($elname, $tempfile, true)) { 00724 // something went wrong 00725 @unlink($tempfile); 00726 return false; 00727 } 00728 00729 return $tempfile; 00730 } 00731 00740 protected function get_draft_files($elname) { 00741 global $USER; 00742 00743 if (!$this->is_submitted()) { 00744 return false; 00745 } 00746 00747 $element = $this->_form->getElement($elname); 00748 00749 if ($element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager) { 00750 $values = $this->_form->exportValues($elname); 00751 if (empty($values[$elname])) { 00752 return false; 00753 } 00754 $draftid = $values[$elname]; 00755 $fs = get_file_storage(); 00756 $context = get_context_instance(CONTEXT_USER, $USER->id); 00757 if (!$files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false)) { 00758 return null; 00759 } 00760 return $files; 00761 } 00762 return null; 00763 } 00764 00778 function save_stored_file($elname, $newcontextid, $newcomponent, $newfilearea, $newitemid, $newfilepath='/', 00779 $newfilename=null, $overwrite=false, $newuserid=null) { 00780 global $USER; 00781 00782 if (!$this->is_submitted() or !$this->is_validated()) { 00783 return false; 00784 } 00785 00786 if (empty($newuserid)) { 00787 $newuserid = $USER->id; 00788 } 00789 00790 $element = $this->_form->getElement($elname); 00791 $fs = get_file_storage(); 00792 00793 if ($element instanceof MoodleQuickForm_filepicker) { 00794 $values = $this->_form->exportValues($elname); 00795 if (empty($values[$elname])) { 00796 return false; 00797 } 00798 $draftid = $values[$elname]; 00799 $context = get_context_instance(CONTEXT_USER, $USER->id); 00800 if (!$files = $fs->get_area_files($context->id, 'user' ,'draft', $draftid, 'id DESC', false)) { 00801 return false; 00802 } 00803 $file = reset($files); 00804 if (is_null($newfilename)) { 00805 $newfilename = $file->get_filename(); 00806 } 00807 00808 if ($overwrite) { 00809 if ($oldfile = $fs->get_file($newcontextid, $newcomponent, $newfilearea, $newitemid, $newfilepath, $newfilename)) { 00810 if (!$oldfile->delete()) { 00811 return false; 00812 } 00813 } 00814 } 00815 00816 $file_record = array('contextid'=>$newcontextid, 'component'=>$newcomponent, 'filearea'=>$newfilearea, 'itemid'=>$newitemid, 00817 'filepath'=>$newfilepath, 'filename'=>$newfilename, 'userid'=>$newuserid); 00818 return $fs->create_file_from_storedfile($file_record, $file); 00819 00820 } else if (isset($_FILES[$elname])) { 00821 $filename = is_null($newfilename) ? $_FILES[$elname]['name'] : $newfilename; 00822 00823 if ($overwrite) { 00824 if ($oldfile = $fs->get_file($newcontextid, $newcomponent, $newfilearea, $newitemid, $newfilepath, $newfilename)) { 00825 if (!$oldfile->delete()) { 00826 return false; 00827 } 00828 } 00829 } 00830 00831 $file_record = array('contextid'=>$newcontextid, 'component'=>$newcomponent, 'filearea'=>$newfilearea, 'itemid'=>$newitemid, 00832 'filepath'=>$newfilepath, 'filename'=>$newfilename, 'userid'=>$newuserid); 00833 return $fs->create_file_from_pathname($file_record, $_FILES[$elname]['tmp_name']); 00834 } 00835 00836 return false; 00837 } 00838 00846 function get_file_content($elname) { 00847 global $USER; 00848 00849 if (!$this->is_submitted() or !$this->is_validated()) { 00850 return false; 00851 } 00852 00853 $element = $this->_form->getElement($elname); 00854 00855 if ($element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager) { 00856 $values = $this->_form->exportValues($elname); 00857 if (empty($values[$elname])) { 00858 return false; 00859 } 00860 $draftid = $values[$elname]; 00861 $fs = get_file_storage(); 00862 $context = get_context_instance(CONTEXT_USER, $USER->id); 00863 if (!$files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false)) { 00864 return false; 00865 } 00866 $file = reset($files); 00867 00868 return $file->get_content(); 00869 00870 } else if (isset($_FILES[$elname])) { 00871 return file_get_contents($_FILES[$elname]['tmp_name']); 00872 } 00873 00874 return false; 00875 } 00876 00880 function display() { 00881 //finalize the form definition if not yet done 00882 if (!$this->_definition_finalized) { 00883 $this->_definition_finalized = true; 00884 $this->definition_after_data(); 00885 } 00886 $this->_form->display(); 00887 } 00888 00892 protected abstract function definition(); 00893 00899 function definition_after_data(){ 00900 } 00901 00914 function validation($data, $files) { 00915 return array(); 00916 } 00917 00924 function repeat_elements_fix_clone($i, $elementclone, &$namecloned) { 00925 $name = $elementclone->getName(); 00926 $namecloned[] = $name; 00927 00928 if (!empty($name)) { 00929 $elementclone->setName($name."[$i]"); 00930 } 00931 00932 if (is_a($elementclone, 'HTML_QuickForm_header')) { 00933 $value = $elementclone->_text; 00934 $elementclone->setValue(str_replace('{no}', ($i+1), $value)); 00935 00936 } else { 00937 $value=$elementclone->getLabel(); 00938 $elementclone->setLabel(str_replace('{no}', ($i+1), $value)); 00939 } 00940 } 00941 00962 function repeat_elements($elementobjs, $repeats, $options, $repeathiddenname, 00963 $addfieldsname, $addfieldsno=5, $addstring=null, $addbuttoninside=false){ 00964 if ($addstring===null){ 00965 $addstring = get_string('addfields', 'form', $addfieldsno); 00966 } else { 00967 $addstring = str_ireplace('{no}', $addfieldsno, $addstring); 00968 } 00969 $repeats = optional_param($repeathiddenname, $repeats, PARAM_INT); 00970 $addfields = optional_param($addfieldsname, '', PARAM_TEXT); 00971 if (!empty($addfields)){ 00972 $repeats += $addfieldsno; 00973 } 00974 $mform =& $this->_form; 00975 $mform->registerNoSubmitButton($addfieldsname); 00976 $mform->addElement('hidden', $repeathiddenname, $repeats); 00977 $mform->setType($repeathiddenname, PARAM_INT); 00978 //value not to be overridden by submitted value 00979 $mform->setConstants(array($repeathiddenname=>$repeats)); 00980 $namecloned = array(); 00981 for ($i = 0; $i < $repeats; $i++) { 00982 foreach ($elementobjs as $elementobj){ 00983 $elementclone = fullclone($elementobj); 00984 $this->repeat_elements_fix_clone($i, $elementclone, $namecloned); 00985 00986 if ($elementclone instanceof HTML_QuickForm_group && !$elementclone->_appendName) { 00987 foreach ($elementclone->getElements() as $el) { 00988 $this->repeat_elements_fix_clone($i, $el, $namecloned); 00989 } 00990 $elementclone->setLabel(str_replace('{no}', $i + 1, $elementclone->getLabel())); 00991 } 00992 00993 $mform->addElement($elementclone); 00994 } 00995 } 00996 for ($i=0; $i<$repeats; $i++) { 00997 foreach ($options as $elementname => $elementoptions){ 00998 $pos=strpos($elementname, '['); 00999 if ($pos!==FALSE){ 01000 $realelementname = substr($elementname, 0, $pos+1)."[$i]"; 01001 $realelementname .= substr($elementname, $pos+1); 01002 }else { 01003 $realelementname = $elementname."[$i]"; 01004 } 01005 foreach ($elementoptions as $option => $params){ 01006 01007 switch ($option){ 01008 case 'default' : 01009 $mform->setDefault($realelementname, $params); 01010 break; 01011 case 'helpbutton' : 01012 $params = array_merge(array($realelementname), $params); 01013 call_user_func_array(array(&$mform, 'addHelpButton'), $params); 01014 break; 01015 case 'disabledif' : 01016 foreach ($namecloned as $num => $name){ 01017 if ($params[0] == $name){ 01018 $params[0] = $params[0]."[$i]"; 01019 break; 01020 } 01021 } 01022 $params = array_merge(array($realelementname), $params); 01023 call_user_func_array(array(&$mform, 'disabledIf'), $params); 01024 break; 01025 case 'rule' : 01026 if (is_string($params)){ 01027 $params = array(null, $params, null, 'client'); 01028 } 01029 $params = array_merge(array($realelementname), $params); 01030 call_user_func_array(array(&$mform, 'addRule'), $params); 01031 break; 01032 case 'type' : 01033 //Type should be set only once 01034 if (!isset($mform->_types[$elementname])) { 01035 $mform->setType($elementname, $params); 01036 } 01037 break; 01038 } 01039 } 01040 } 01041 } 01042 $mform->addElement('submit', $addfieldsname, $addstring); 01043 01044 if (!$addbuttoninside) { 01045 $mform->closeHeaderBefore($addfieldsname); 01046 } 01047 01048 return $repeats; 01049 } 01050 01060 function add_checkbox_controller($groupid, $text = null, $attributes = null, $originalValue = 0) { 01061 global $CFG; 01062 01063 // Set the default text if none was specified 01064 if (empty($text)) { 01065 $text = get_string('selectallornone', 'form'); 01066 } 01067 01068 $mform = $this->_form; 01069 $select_value = optional_param('checkbox_controller'. $groupid, null, PARAM_INT); 01070 01071 if ($select_value == 0 || is_null($select_value)) { 01072 $new_select_value = 1; 01073 } else { 01074 $new_select_value = 0; 01075 } 01076 01077 $mform->addElement('hidden', "checkbox_controller$groupid"); 01078 $mform->setType("checkbox_controller$groupid", PARAM_INT); 01079 $mform->setConstants(array("checkbox_controller$groupid" => $new_select_value)); 01080 01081 $checkbox_controller_name = 'nosubmit_checkbox_controller' . $groupid; 01082 $mform->registerNoSubmitButton($checkbox_controller_name); 01083 01084 // Prepare Javascript for submit element 01085 $js = "\n//<![CDATA[\n"; 01086 if (!defined('HTML_QUICKFORM_CHECKBOXCONTROLLER_EXISTS')) { 01087 $js .= <<<EOS 01088 function html_quickform_toggle_checkboxes(group) { 01089 var checkboxes = document.getElementsByClassName('checkboxgroup' + group); 01090 var newvalue = false; 01091 var global = eval('html_quickform_checkboxgroup' + group + ';'); 01092 if (global == 1) { 01093 eval('html_quickform_checkboxgroup' + group + ' = 0;'); 01094 newvalue = ''; 01095 } else { 01096 eval('html_quickform_checkboxgroup' + group + ' = 1;'); 01097 newvalue = 'checked'; 01098 } 01099 01100 for (i = 0; i < checkboxes.length; i++) { 01101 checkboxes[i].checked = newvalue; 01102 } 01103 } 01104 EOS; 01105 define('HTML_QUICKFORM_CHECKBOXCONTROLLER_EXISTS', true); 01106 } 01107 $js .= "\nvar html_quickform_checkboxgroup$groupid=$originalValue;\n"; 01108 01109 $js .= "//]]>\n"; 01110 01111 require_once("$CFG->libdir/form/submitlink.php"); 01112 $submitlink = new MoodleQuickForm_submitlink($checkbox_controller_name, $attributes); 01113 $submitlink->_js = $js; 01114 $submitlink->_onclick = "html_quickform_toggle_checkboxes($groupid); return false;"; 01115 $mform->addElement($submitlink); 01116 $mform->setDefault($checkbox_controller_name, $text); 01117 } 01118 01128 function add_action_buttons($cancel = true, $submitlabel=null){ 01129 if (is_null($submitlabel)){ 01130 $submitlabel = get_string('savechanges'); 01131 } 01132 $mform =& $this->_form; 01133 if ($cancel){ 01134 //when two elements we need a group 01135 $buttonarray=array(); 01136 $buttonarray[] = &$mform->createElement('submit', 'submitbutton', $submitlabel); 01137 $buttonarray[] = &$mform->createElement('cancel'); 01138 $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); 01139 $mform->closeHeaderBefore('buttonar'); 01140 } else { 01141 //no group needed 01142 $mform->addElement('submit', 'submitbutton', $submitlabel); 01143 $mform->closeHeaderBefore('submitbutton'); 01144 } 01145 } 01146 01166 function init_javascript_enhancement($element, $enhancement, array $options=array(), array $strings=null) { 01167 global $PAGE; 01168 if (is_string($element)) { 01169 $element = $this->_form->getElement($element); 01170 } 01171 if (is_object($element)) { 01172 $element->_generateId(); 01173 $elementid = $element->getAttribute('id'); 01174 $PAGE->requires->js_init_call('M.form.init_'.$enhancement, array($elementid, $options)); 01175 if (is_array($strings)) { 01176 foreach ($strings as $string) { 01177 if (is_array($string)) { 01178 call_user_method_array('string_for_js', $PAGE->requires, $string); 01179 } else { 01180 $PAGE->requires->string_for_js($string, 'moodle'); 01181 } 01182 } 01183 } 01184 } 01185 } 01186 01191 public static function get_js_module() { 01192 global $CFG; 01193 return array( 01194 'name' => 'mform', 01195 'fullpath' => '/lib/form/form.js', 01196 'requires' => array('base', 'node'), 01197 'strings' => array( 01198 array('showadvanced', 'form'), 01199 array('hideadvanced', 'form') 01200 ) 01201 ); 01202 } 01203 } 01204 01215 class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { 01217 var $_types = array(); 01218 var $_dependencies = array(); 01224 var $_noSubmitButtons=array(); 01230 var $_cancelButtons=array(); 01231 01237 var $_advancedElements = array(); 01238 01244 var $_showAdvanced = null; 01245 01253 var $_formName = ''; 01254 01260 var $_pageparams = ''; 01261 01274 function MoodleQuickForm($formName, $method, $action, $target='', $attributes=null){ 01275 global $CFG, $OUTPUT; 01276 01277 static $formcounter = 1; 01278 01279 HTML_Common::HTML_Common($attributes); 01280 $target = empty($target) ? array() : array('target' => $target); 01281 $this->_formName = $formName; 01282 if (is_a($action, 'moodle_url')){ 01283 $this->_pageparams = html_writer::input_hidden_params($action); 01284 $action = $action->out_omit_querystring(); 01285 } else { 01286 $this->_pageparams = ''; 01287 } 01288 //no 'name' atttribute for form in xhtml strict : 01289 $attributes = array('action'=>$action, 'method'=>$method, 01290 'accept-charset'=>'utf-8', 'id'=>'mform'.$formcounter) + $target; 01291 $formcounter++; 01292 $this->updateAttributes($attributes); 01293 01294 //this is custom stuff for Moodle : 01295 $oldclass= $this->getAttribute('class'); 01296 if (!empty($oldclass)){ 01297 $this->updateAttributes(array('class'=>$oldclass.' mform')); 01298 }else { 01299 $this->updateAttributes(array('class'=>'mform')); 01300 } 01301 $this->_reqHTML = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />'; 01302 $this->_advancedHTML = '<img class="adv" title="'.get_string('advancedelement', 'form').'" alt="'.get_string('advancedelement', 'form').'" src="'.$OUTPUT->pix_url('adv') .'" />'; 01303 $this->setRequiredNote(get_string('somefieldsrequired', 'form', '<img alt="'.get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />')); 01304 } 01305 01316 function setAdvanced($elementName, $advanced=true){ 01317 if ($advanced){ 01318 $this->_advancedElements[$elementName]=''; 01319 } elseif (isset($this->_advancedElements[$elementName])) { 01320 unset($this->_advancedElements[$elementName]); 01321 } 01322 if ($advanced && $this->getElementType('mform_showadvanced_last')===false){ 01323 $this->setShowAdvanced(); 01324 $this->registerNoSubmitButton('mform_showadvanced'); 01325 01326 $this->addElement('hidden', 'mform_showadvanced_last'); 01327 $this->setType('mform_showadvanced_last', PARAM_INT); 01328 } 01329 } 01339 function setShowAdvanced($showadvancedNow = null){ 01340 if ($showadvancedNow === null){ 01341 if ($this->_showAdvanced !== null){ 01342 return; 01343 } else { //if setShowAdvanced is called without any preference 01344 //make the default to not show advanced elements. 01345 $showadvancedNow = get_user_preferences( 01346 moodle_strtolower($this->_formName.'_showadvanced', 0)); 01347 } 01348 } 01349 //value of hidden element 01350 $hiddenLast = optional_param('mform_showadvanced_last', -1, PARAM_INT); 01351 //value of button 01352 $buttonPressed = optional_param('mform_showadvanced', 0, PARAM_RAW); 01353 //toggle if button pressed or else stay the same 01354 if ($hiddenLast == -1) { 01355 $next = $showadvancedNow; 01356 } elseif ($buttonPressed) { //toggle on button press 01357 $next = !$hiddenLast; 01358 } else { 01359 $next = $hiddenLast; 01360 } 01361 $this->_showAdvanced = $next; 01362 if ($showadvancedNow != $next){ 01363 set_user_preference($this->_formName.'_showadvanced', $next); 01364 } 01365 $this->setConstants(array('mform_showadvanced_last'=>$next)); 01366 } 01367 function getShowAdvanced(){ 01368 return $this->_showAdvanced; 01369 } 01370 01371 01379 function accept(&$renderer) { 01380 if (method_exists($renderer, 'setAdvancedElements')){ 01381 //check for visible fieldsets where all elements are advanced 01382 //and mark these headers as advanced as well. 01383 //And mark all elements in a advanced header as advanced 01384 $stopFields = $renderer->getStopFieldSetElements(); 01385 $lastHeader = null; 01386 $lastHeaderAdvanced = false; 01387 $anyAdvanced = false; 01388 foreach (array_keys($this->_elements) as $elementIndex){ 01389 $element =& $this->_elements[$elementIndex]; 01390 01391 // if closing header and any contained element was advanced then mark it as advanced 01392 if ($element->getType()=='header' || in_array($element->getName(), $stopFields)){ 01393 if ($anyAdvanced && !is_null($lastHeader)){ 01394 $this->setAdvanced($lastHeader->getName()); 01395 } 01396 $lastHeaderAdvanced = false; 01397 unset($lastHeader); 01398 $lastHeader = null; 01399 } elseif ($lastHeaderAdvanced) { 01400 $this->setAdvanced($element->getName()); 01401 } 01402 01403 if ($element->getType()=='header'){ 01404 $lastHeader =& $element; 01405 $anyAdvanced = false; 01406 $lastHeaderAdvanced = isset($this->_advancedElements[$element->getName()]); 01407 } elseif (isset($this->_advancedElements[$element->getName()])){ 01408 $anyAdvanced = true; 01409 } 01410 } 01411 // the last header may not be closed yet... 01412 if ($anyAdvanced && !is_null($lastHeader)){ 01413 $this->setAdvanced($lastHeader->getName()); 01414 } 01415 $renderer->setAdvancedElements($this->_advancedElements); 01416 01417 } 01418 parent::accept($renderer); 01419 } 01420 01424 function closeHeaderBefore($elementName){ 01425 $renderer =& $this->defaultRenderer(); 01426 $renderer->addStopFieldsetElements($elementName); 01427 } 01428 01447 function setType($elementname, $paramtype) { 01448 $this->_types[$elementname] = $paramtype; 01449 } 01450 01456 function setTypes($paramtypes) { 01457 $this->_types = $paramtypes + $this->_types; 01458 } 01459 01464 function updateSubmission($submission, $files) { 01465 $this->_flagSubmitted = false; 01466 01467 if (empty($submission)) { 01468 $this->_submitValues = array(); 01469 } else { 01470 foreach ($submission as $key=>$s) { 01471 if (array_key_exists($key, $this->_types)) { 01472 $type = $this->_types[$key]; 01473 } else { 01474 $type = PARAM_RAW; 01475 } 01476 if (is_array($s)) { 01477 $submission[$key] = clean_param_array($s, $type, true); 01478 } else { 01479 $submission[$key] = clean_param($s, $type); 01480 } 01481 } 01482 $this->_submitValues = $submission; 01483 $this->_flagSubmitted = true; 01484 } 01485 01486 if (empty($files)) { 01487 $this->_submitFiles = array(); 01488 } else { 01489 $this->_submitFiles = $files; 01490 $this->_flagSubmitted = true; 01491 } 01492 01493 // need to tell all elements that they need to update their value attribute. 01494 foreach (array_keys($this->_elements) as $key) { 01495 $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); 01496 } 01497 } 01498 01502 function getReqHTML(){ 01503 return $this->_reqHTML; 01504 } 01505 01509 function getAdvancedHTML(){ 01510 return $this->_advancedHTML; 01511 } 01512 01524 function setDefault($elementName, $defaultValue){ 01525 $this->setDefaults(array($elementName=>$defaultValue)); 01526 } // end func setDefault 01536 function setHelpButtons($buttons, $suppresscheck=false, $function='helpbutton'){ 01537 01538 debugging('function moodle_form::setHelpButtons() is deprecated'); 01539 //foreach ($buttons as $elementname => $button){ 01540 // $this->setHelpButton($elementname, $button, $suppresscheck, $function); 01541 //} 01542 } 01554 function setHelpButton($elementname, $buttonargs, $suppresscheck=false, $function='helpbutton'){ 01555 global $OUTPUT; 01556 01557 debugging('function moodle_form::setHelpButton() is deprecated'); 01558 if ($function !== 'helpbutton') { 01559 //debugging('parameter $function in moodle_form::setHelpButton() is not supported any more'); 01560 } 01561 01562 $buttonargs = (array)$buttonargs; 01563 01564 if (array_key_exists($elementname, $this->_elementIndex)) { 01565 //_elements has a numeric index, this code accesses the elements by name 01566 $element = $this->_elements[$this->_elementIndex[$elementname]]; 01567 01568 $page = isset($buttonargs[0]) ? $buttonargs[0] : null; 01569 $text = isset($buttonargs[1]) ? $buttonargs[1] : null; 01570 $module = isset($buttonargs[2]) ? $buttonargs[2] : 'moodle'; 01571 $linktext = isset($buttonargs[3]) ? $buttonargs[3] : false; 01572 01573 $element->_helpbutton = $OUTPUT->old_help_icon($page, $text, $module, $linktext); 01574 01575 } else if (!$suppresscheck) { 01576 print_error('nonexistentformelements', 'form', '', $elementname); 01577 } 01578 } 01579 01602 function addHelpButton($elementname, $identifier, $component = 'moodle', $linktext = '', $suppresscheck = false) { 01603 global $OUTPUT; 01604 if (array_key_exists($elementname, $this->_elementIndex)) { 01605 $element = $this->_elements[$this->_elementIndex[$elementname]]; 01606 $element->_helpbutton = $OUTPUT->help_icon($identifier, $component, $linktext); 01607 } else if (!$suppresscheck) { 01608 debugging(get_string('nonexistentformelements', 'form', $elementname)); 01609 } 01610 } 01611 01620 function setConstant($elname, $value) { 01621 $this->_constantValues = HTML_QuickForm::arrayMerge($this->_constantValues, array($elname=>$value)); 01622 $element =& $this->getElement($elname); 01623 $element->onQuickFormEvent('updateValue', null, $this); 01624 } 01625 01629 function exportValues($elementList = null){ 01630 $unfiltered = array(); 01631 if (null === $elementList) { 01632 // iterate over all elements, calling their exportValue() methods 01633 $emptyarray = array(); 01634 foreach (array_keys($this->_elements) as $key) { 01635 if ($this->_elements[$key]->isFrozen() && !$this->_elements[$key]->_persistantFreeze){ 01636 $value = $this->_elements[$key]->exportValue($emptyarray, true); 01637 } else { 01638 $value = $this->_elements[$key]->exportValue($this->_submitValues, true); 01639 } 01640 01641 if (is_array($value)) { 01642 // This shit throws a bogus warning in PHP 4.3.x 01643 $unfiltered = HTML_QuickForm::arrayMerge($unfiltered, $value); 01644 } 01645 } 01646 } else { 01647 if (!is_array($elementList)) { 01648 $elementList = array_map('trim', explode(',', $elementList)); 01649 } 01650 foreach ($elementList as $elementName) { 01651 $value = $this->exportValue($elementName); 01652 if (PEAR::isError($value)) { 01653 return $value; 01654 } 01655 //oh, stock QuickFOrm was returning array of arrays! 01656 $unfiltered = HTML_QuickForm::arrayMerge($unfiltered, $value); 01657 } 01658 } 01659 01660 if (is_array($this->_constantValues)) { 01661 $unfiltered = HTML_QuickForm::arrayMerge($unfiltered, $this->_constantValues); 01662 } 01663 01664 return $unfiltered; 01665 } 01682 function addRule($element, $message, $type, $format=null, $validation='server', $reset = false, $force = false) 01683 { 01684 parent::addRule($element, $message, $type, $format, $validation, $reset, $force); 01685 if ($validation == 'client') { 01686 $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_formName . '; } catch(e) { return true; } return myValidator(this);')); 01687 } 01688 01689 } // end func addRule 01708 function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false) 01709 { 01710 parent::addGroupRule($group, $arg1, $type, $format, $howmany, $validation, $reset); 01711 if (is_array($arg1)) { 01712 foreach ($arg1 as $rules) { 01713 foreach ($rules as $rule) { 01714 $validation = (isset($rule[3]) && 'client' == $rule[3])? 'client': 'server'; 01715 01716 if ('client' == $validation) { 01717 $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_formName . '; } catch(e) { return true; } return myValidator(this);')); 01718 } 01719 } 01720 } 01721 } elseif (is_string($arg1)) { 01722 01723 if ($validation == 'client') { 01724 $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_formName . '; } catch(e) { return true; } return myValidator(this);')); 01725 } 01726 } 01727 } // end func addGroupRule 01728 01729 // }}} 01740 function getValidationScript() 01741 { 01742 if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) { 01743 return ''; 01744 } 01745 01746 include_once('HTML/QuickForm/RuleRegistry.php'); 01747 $registry =& HTML_QuickForm_RuleRegistry::singleton(); 01748 $test = array(); 01749 $js_escape = array( 01750 "\r" => '\r', 01751 "\n" => '\n', 01752 "\t" => '\t', 01753 "'" => "\\'", 01754 '"' => '\"', 01755 '\\' => '\\\\' 01756 ); 01757 01758 foreach ($this->_rules as $elementName => $rules) { 01759 foreach ($rules as $rule) { 01760 if ('client' == $rule['validation']) { 01761 unset($element); //TODO: find out how to properly initialize it 01762 01763 $dependent = isset($rule['dependent']) && is_array($rule['dependent']); 01764 $rule['message'] = strtr($rule['message'], $js_escape); 01765 01766 if (isset($rule['group'])) { 01767 $group =& $this->getElement($rule['group']); 01768 // No JavaScript validation for frozen elements 01769 if ($group->isFrozen()) { 01770 continue 2; 01771 } 01772 $elements =& $group->getElements(); 01773 foreach (array_keys($elements) as $key) { 01774 if ($elementName == $group->getElementName($key)) { 01775 $element =& $elements[$key]; 01776 break; 01777 } 01778 } 01779 } elseif ($dependent) { 01780 $element = array(); 01781 $element[] =& $this->getElement($elementName); 01782 foreach ($rule['dependent'] as $elName) { 01783 $element[] =& $this->getElement($elName); 01784 } 01785 } else { 01786 $element =& $this->getElement($elementName); 01787 } 01788 // No JavaScript validation for frozen elements 01789 if (is_object($element) && $element->isFrozen()) { 01790 continue 2; 01791 } elseif (is_array($element)) { 01792 foreach (array_keys($element) as $key) { 01793 if ($element[$key]->isFrozen()) { 01794 continue 3; 01795 } 01796 } 01797 } 01798 //for editor element, [text] is appended to the name. 01799 if ($element->getType() == 'editor') { 01800 $elementName .= '[text]'; 01801 //Add format to rule as moodleform check which format is supported by browser 01802 //it is not set anywhere... So small hack to make sure we pass it down to quickform 01803 if (is_null($rule['format'])) { 01804 $rule['format'] = $element->getFormat(); 01805 } 01806 } 01807 // Fix for bug displaying errors for elements in a group 01808 $test[$elementName][0][] = $registry->getValidationScript($element, $elementName, $rule); 01809 $test[$elementName][1]=$element; 01810 //end of fix 01811 } 01812 } 01813 } 01814 01815 // Fix for MDL-9524. If you don't do this, then $element may be left as a reference to one of the fields in 01816 // the form, and then that form field gets corrupted by the code that follows. 01817 unset($element); 01818 01819 $js = ' 01820 <script type="text/javascript"> 01821 //<![CDATA[ 01822 01823 var skipClientValidation = false; 01824 01825 function qf_errorHandler(element, _qfMsg) { 01826 div = element.parentNode; 01827 01828 if ((div == undefined) || (element.name == undefined)) { 01829 //no checking can be done for undefined elements so let server handle it. 01830 return true; 01831 } 01832 01833 if (_qfMsg != \'\') { 01834 var errorSpan = document.getElementById(\'id_error_\'+element.name); 01835 if (!errorSpan) { 01836 errorSpan = document.createElement("span"); 01837 errorSpan.id = \'id_error_\'+element.name; 01838 errorSpan.className = "error"; 01839 element.parentNode.insertBefore(errorSpan, element.parentNode.firstChild); 01840 } 01841 01842 while (errorSpan.firstChild) { 01843 errorSpan.removeChild(errorSpan.firstChild); 01844 } 01845 01846 errorSpan.appendChild(document.createTextNode(_qfMsg.substring(3))); 01847 errorSpan.appendChild(document.createElement("br")); 01848 01849 if (div.className.substr(div.className.length - 6, 6) != " error" 01850 && div.className != "error") { 01851 div.className += " error"; 01852 } 01853 01854 return false; 01855 } else { 01856 var errorSpan = document.getElementById(\'id_error_\'+element.name); 01857 if (errorSpan) { 01858 errorSpan.parentNode.removeChild(errorSpan); 01859 } 01860 01861 if (div.className.substr(div.className.length - 6, 6) == " error") { 01862 div.className = div.className.substr(0, div.className.length - 6); 01863 } else if (div.className == "error") { 01864 div.className = ""; 01865 } 01866 01867 return true; 01868 } 01869 }'; 01870 $validateJS = ''; 01871 foreach ($test as $elementName => $jsandelement) { 01872 // Fix for bug displaying errors for elements in a group 01873 //unset($element); 01874 list($jsArr,$element)=$jsandelement; 01875 //end of fix 01876 $escapedElementName = preg_replace_callback( 01877 '/[_\[\]]/', 01878 create_function('$matches', 'return sprintf("_%2x",ord($matches[0]));'), 01879 $elementName); 01880 $js .= ' 01881 function validate_' . $this->_formName . '_' . $escapedElementName . '(element) { 01882 if (undefined == element) { 01883 //required element was not found, then let form be submitted without client side validation 01884 return true; 01885 } 01886 var value = \'\'; 01887 var errFlag = new Array(); 01888 var _qfGroups = {}; 01889 var _qfMsg = \'\'; 01890 var frm = element.parentNode; 01891 if ((undefined != element.name) && (frm != undefined)) { 01892 while (frm && frm.nodeName.toUpperCase() != "FORM") { 01893 frm = frm.parentNode; 01894 } 01895 ' . join("\n", $jsArr) . ' 01896 return qf_errorHandler(element, _qfMsg); 01897 } else { 01898 //element name should be defined else error msg will not be displayed. 01899 return true; 01900 } 01901 } 01902 '; 01903 $validateJS .= ' 01904 ret = validate_' . $this->_formName . '_' . $escapedElementName.'(frm.elements[\''.$elementName.'\']) && ret; 01905 if (!ret && !first_focus) { 01906 first_focus = true; 01907 frm.elements[\''.$elementName.'\'].focus(); 01908 } 01909 '; 01910 01911 // Fix for bug displaying errors for elements in a group 01912 //unset($element); 01913 //$element =& $this->getElement($elementName); 01914 //end of fix 01915 $valFunc = 'validate_' . $this->_formName . '_' . $escapedElementName . '(this)'; 01916 $onBlur = $element->getAttribute('onBlur'); 01917 $onChange = $element->getAttribute('onChange'); 01918 $element->updateAttributes(array('onBlur' => $onBlur . $valFunc, 01919 'onChange' => $onChange . $valFunc)); 01920 } 01921 // do not rely on frm function parameter, because htmlarea breaks it when overloading the onsubmit method 01922 $js .= ' 01923 function validate_' . $this->_formName . '(frm) { 01924 if (skipClientValidation) { 01925 return true; 01926 } 01927 var ret = true; 01928 01929 var frm = document.getElementById(\''. $this->_attributes['id'] .'\') 01930 var first_focus = false; 01931 ' . $validateJS . '; 01932 return ret; 01933 } 01934 //]]> 01935 </script>'; 01936 return $js; 01937 } // end func getValidationScript 01938 function _setDefaultRuleMessages(){ 01939 foreach ($this->_rules as $field => $rulesarr){ 01940 foreach ($rulesarr as $key => $rule){ 01941 if ($rule['message']===null){ 01942 $a=new stdClass(); 01943 $a->format=$rule['format']; 01944 $str=get_string('err_'.$rule['type'], 'form', $a); 01945 if (strpos($str, '[[')!==0){ 01946 $this->_rules[$field][$key]['message']=$str; 01947 } 01948 } 01949 } 01950 } 01951 } 01952 01953 function getLockOptionObject(){ 01954 $result = array(); 01955 foreach ($this->_dependencies as $dependentOn => $conditions){ 01956 $result[$dependentOn] = array(); 01957 foreach ($conditions as $condition=>$values) { 01958 $result[$dependentOn][$condition] = array(); 01959 foreach ($values as $value=>$dependents) { 01960 $result[$dependentOn][$condition][$value] = array(); 01961 $i = 0; 01962 foreach ($dependents as $dependent) { 01963 $elements = $this->_getElNamesRecursive($dependent); 01964 if (empty($elements)) { 01965 // probably element inside of some group 01966 $elements = array($dependent); 01967 } 01968 foreach($elements as $element) { 01969 if ($element == $dependentOn) { 01970 continue; 01971 } 01972 $result[$dependentOn][$condition][$value][] = $element; 01973 } 01974 } 01975 } 01976 } 01977 } 01978 return array($this->getAttribute('id'), $result); 01979 } 01980 01985 function _getElNamesRecursive($element) { 01986 if (is_string($element)) { 01987 if (!$this->elementExists($element)) { 01988 return array(); 01989 } 01990 $element = $this->getElement($element); 01991 } 01992 01993 if (is_a($element, 'HTML_QuickForm_group')) { 01994 $elsInGroup = $element->getElements(); 01995 $elNames = array(); 01996 foreach ($elsInGroup as $elInGroup){ 01997 if (is_a($elInGroup, 'HTML_QuickForm_group')) { 01998 // not sure if this would work - groups nested in groups 01999 $elNames = array_merge($elNames, $this->_getElNamesRecursive($elInGroup)); 02000 } else { 02001 $elNames[] = $element->getElementName($elInGroup->getName()); 02002 } 02003 } 02004 02005 } else if (is_a($element, 'HTML_QuickForm_header')) { 02006 return array(); 02007 02008 } else if (is_a($element, 'HTML_QuickForm_hidden')) { 02009 return array(); 02010 02011 } else if (method_exists($element, 'getPrivateName') && 02012 !($element instanceof HTML_QuickForm_advcheckbox)) { 02013 // The advcheckbox element implements a method called getPrivateName, 02014 // but in a way that is not compatible with the generic API, so we 02015 // have to explicitly exclude it. 02016 return array($element->getPrivateName()); 02017 02018 } else { 02019 $elNames = array($element->getName()); 02020 } 02021 02022 return $elNames; 02023 } 02024 02038 function disabledIf($elementName, $dependentOn, $condition = 'notchecked', $value='1'){ 02039 if (!array_key_exists($dependentOn, $this->_dependencies)) { 02040 $this->_dependencies[$dependentOn] = array(); 02041 } 02042 if (!array_key_exists($condition, $this->_dependencies[$dependentOn])) { 02043 $this->_dependencies[$dependentOn][$condition] = array(); 02044 } 02045 if (!array_key_exists($value, $this->_dependencies[$dependentOn][$condition])) { 02046 $this->_dependencies[$dependentOn][$condition][$value] = array(); 02047 } 02048 $this->_dependencies[$dependentOn][$condition][$value][] = $elementName; 02049 } 02050 02051 function registerNoSubmitButton($buttonname){ 02052 $this->_noSubmitButtons[]=$buttonname; 02053 } 02054 02059 function isNoSubmitButton($buttonname){ 02060 return (array_search($buttonname, $this->_noSubmitButtons)!==FALSE); 02061 } 02062 02066 function _registerCancelButton($addfieldsname){ 02067 $this->_cancelButtons[]=$addfieldsname; 02068 } 02080 function hardFreeze($elementList=null) 02081 { 02082 if (!isset($elementList)) { 02083 $this->_freezeAll = true; 02084 $elementList = array(); 02085 } else { 02086 if (!is_array($elementList)) { 02087 $elementList = preg_split('/[ ]*,[ ]*/', $elementList); 02088 } 02089 $elementList = array_flip($elementList); 02090 } 02091 02092 foreach (array_keys($this->_elements) as $key) { 02093 $name = $this->_elements[$key]->getName(); 02094 if ($this->_freezeAll || isset($elementList[$name])) { 02095 $this->_elements[$key]->freeze(); 02096 $this->_elements[$key]->setPersistantFreeze(false); 02097 unset($elementList[$name]); 02098 02099 // remove all rules 02100 $this->_rules[$name] = array(); 02101 // if field is required, remove the rule 02102 $unset = array_search($name, $this->_required); 02103 if ($unset !== false) { 02104 unset($this->_required[$unset]); 02105 } 02106 } 02107 } 02108 02109 if (!empty($elementList)) { 02110 return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Nonexistant element(s): '" . implode("', '", array_keys($elementList)) . "' in HTML_QuickForm::freeze()", 'HTML_QuickForm_Error', true); 02111 } 02112 return true; 02113 } 02124 function hardFreezeAllVisibleExcept($elementList) 02125 { 02126 $elementList = array_flip($elementList); 02127 foreach (array_keys($this->_elements) as $key) { 02128 $name = $this->_elements[$key]->getName(); 02129 $type = $this->_elements[$key]->getType(); 02130 02131 if ($type == 'hidden'){ 02132 // leave hidden types as they are 02133 } elseif (!isset($elementList[$name])) { 02134 $this->_elements[$key]->freeze(); 02135 $this->_elements[$key]->setPersistantFreeze(false); 02136 02137 // remove all rules 02138 $this->_rules[$name] = array(); 02139 // if field is required, remove the rule 02140 $unset = array_search($name, $this->_required); 02141 if ($unset !== false) { 02142 unset($this->_required[$unset]); 02143 } 02144 } 02145 } 02146 return true; 02147 } 02157 function isSubmitted() 02158 { 02159 return parent::isSubmitted() && (!$this->isFrozen()); 02160 } 02161 } 02162 02163 02174 class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ 02175 02181 var $_elementTemplates; 02188 var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\"><div>"; 02194 var $_headerTemplate = 02195 "\n\t\t<legend class=\"ftoggler\">{header}</legend>\n\t\t<div class=\"advancedbutton\">{advancedimg}{button}</div><div class=\"fcontainer clearfix\">\n\t\t"; 02196 02202 var $_openFieldsetTemplate = "\n\t<fieldset class=\"clearfix\" {id}>"; 02203 02209 var $_closeFieldsetTemplate = "\n\t\t</div></fieldset>"; 02210 02216 var $_requiredNoteTemplate = 02217 "\n\t\t<div class=\"fdescription required\">{requiredNote}</div>"; 02218 02219 var $_advancedElements = array(); 02220 02226 var $_showAdvanced; 02227 02228 function MoodleQuickForm_Renderer(){ 02229 // switch next two lines for ol li containers for form items. 02230 // $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>'); 02231 $this->_elementTemplates = array( 02232 'default'=>"\n\t\t".'<div id="{id}" class="fitem {advanced}<!-- BEGIN required --> required<!-- END required --> fitem_{type}"><div class="fitemtitle"><label>{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} {help}</label></div><div class="felement {type}<!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error">{error}</span><br /><!-- END error -->{element}</div></div>', 02233 02234 'fieldset'=>"\n\t\t".'<div id="{id}" class="fitem {advanced}<!-- BEGIN required --> required<!-- END required --> fitem_{type}"><div class="fitemtitle"><div class="fgrouplabel"><label>{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} {help}</label></div></div><fieldset class="felement {type}<!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error">{error}</span><br /><!-- END error -->{element}</fieldset></div>', 02235 02236 'static'=>"\n\t\t".'<div class="fitem {advanced}"><div class="fitemtitle"><div class="fstaticlabel"><label>{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} {help}</label></div></div><div class="felement fstatic <!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error">{error}</span><br /><!-- END error -->{element} </div></div>', 02237 02238 'warning'=>"\n\t\t".'<div class="fitem {advanced}">{element}</div>', 02239 02240 'nodisplay'=>''); 02241 02242 parent::HTML_QuickForm_Renderer_Tableless(); 02243 } 02244 02248 function setAdvancedElements($elements){ 02249 $this->_advancedElements = $elements; 02250 } 02251 02257 function startForm(&$form){ 02258 $this->_reqHTML = $form->getReqHTML(); 02259 $this->_elementTemplates = str_replace('{req}', $this->_reqHTML, $this->_elementTemplates); 02260 $this->_advancedHTML = $form->getAdvancedHTML(); 02261 $this->_showAdvanced = $form->getShowAdvanced(); 02262 parent::startForm($form); 02263 if ($form->isFrozen()){ 02264 $this->_formTemplate = "\n<div class=\"mform frozen\">\n{content}\n</div>"; 02265 } else { 02266 $this->_formTemplate = "\n<form{attributes}>\n\t<div style=\"display: none;\">{hidden}</div>\n{content}\n</form>"; 02267 $this->_hiddenHtml .= $form->_pageparams; 02268 } 02269 02270 02271 } 02272 02278 function startGroup(&$group, $required, $error){ 02279 // Make sure the element has an id. 02280 $group->_generateId(); 02281 02282 if (method_exists($group, 'getElementTemplateType')){ 02283 $html = $this->_elementTemplates[$group->getElementTemplateType()]; 02284 }else{ 02285 $html = $this->_elementTemplates['default']; 02286 02287 } 02288 if ($this->_showAdvanced){ 02289 $advclass = ' advanced'; 02290 } else { 02291 $advclass = ' advanced hide'; 02292 } 02293 if (isset($this->_advancedElements[$group->getName()])){ 02294 $html =str_replace(' {advanced}', $advclass, $html); 02295 $html =str_replace('{advancedimg}', $this->_advancedHTML, $html); 02296 } else { 02297 $html =str_replace(' {advanced}', '', $html); 02298 $html =str_replace('{advancedimg}', '', $html); 02299 } 02300 if (method_exists($group, 'getHelpButton')){ 02301 $html =str_replace('{help}', $group->getHelpButton(), $html); 02302 }else{ 02303 $html =str_replace('{help}', '', $html); 02304 } 02305 $html =str_replace('{id}', 'fgroup_' . $group->getAttribute('id'), $html); 02306 $html =str_replace('{name}', $group->getName(), $html); 02307 $html =str_replace('{type}', 'fgroup', $html); 02308 02309 $this->_templates[$group->getName()]=$html; 02310 // Fix for bug in tableless quickforms that didn't allow you to stop a 02311 // fieldset before a group of elements. 02312 // if the element name indicates the end of a fieldset, close the fieldset 02313 if ( in_array($group->getName(), $this->_stopFieldsetElements) 02314 && $this->_fieldsetsOpen > 0 02315 ) { 02316 $this->_html .= $this->_closeFieldsetTemplate; 02317 $this->_fieldsetsOpen--; 02318 } 02319 parent::startGroup($group, $required, $error); 02320 } 02326 function renderElement(&$element, $required, $error){ 02327 // Make sure the element has an id. 02328 $element->_generateId(); 02329 02330 //adding stuff to place holders in template 02331 //check if this is a group element first 02332 if (($this->_inGroup) and !empty($this->_groupElementTemplate)) { 02333 // so it gets substitutions for *each* element 02334 $html = $this->_groupElementTemplate; 02335 } 02336 elseif (method_exists($element, 'getElementTemplateType')){ 02337 $html = $this->_elementTemplates[$element->getElementTemplateType()]; 02338 }else{ 02339 $html = $this->_elementTemplates['default']; 02340 } 02341 if ($this->_showAdvanced){ 02342 $advclass = ' advanced'; 02343 } else { 02344 $advclass = ' advanced hide'; 02345 } 02346 if (isset($this->_advancedElements[$element->getName()])){ 02347 $html =str_replace(' {advanced}', $advclass, $html); 02348 } else { 02349 $html =str_replace(' {advanced}', '', $html); 02350 } 02351 if (isset($this->_advancedElements[$element->getName()])||$element->getName() == 'mform_showadvanced'){ 02352 $html =str_replace('{advancedimg}', $this->_advancedHTML, $html); 02353 } else { 02354 $html =str_replace('{advancedimg}', '', $html); 02355 } 02356 $html =str_replace('{id}', 'fitem_' . $element->getAttribute('id'), $html); 02357 $html =str_replace('{type}', 'f'.$element->getType(), $html); 02358 $html =str_replace('{name}', $element->getName(), $html); 02359 if (method_exists($element, 'getHelpButton')){ 02360 $html = str_replace('{help}', $element->getHelpButton(), $html); 02361 }else{ 02362 $html = str_replace('{help}', '', $html); 02363 02364 } 02365 if (($this->_inGroup) and !empty($this->_groupElementTemplate)) { 02366 $this->_groupElementTemplate = $html; 02367 } 02368 elseif (!isset($this->_templates[$element->getName()])) { 02369 $this->_templates[$element->getName()] = $html; 02370 } 02371 02372 parent::renderElement($element, $required, $error); 02373 } 02374 02379 function finishForm(&$form){ 02380 global $PAGE; 02381 if ($form->isFrozen()){ 02382 $this->_hiddenHtml = ''; 02383 } 02384 parent::finishForm($form); 02385 if (!$form->isFrozen()) { 02386 $args = $form->getLockOptionObject(); 02387 if (count($args[1]) > 0) { 02388 $PAGE->requires->js_init_call('M.form.initFormDependencies', $args, true, moodleform::get_js_module()); 02389 } 02390 } 02391 } 02400 function renderHeader(&$header) { 02401 global $PAGE; 02402 02403 $name = $header->getName(); 02404 02405 $id = empty($name) ? '' : ' id="' . $name . '"'; 02406 $id = preg_replace(array('/\]/', '/\[/'), array('', '_'), $id); 02407 if (is_null($header->_text)) { 02408 $header_html = ''; 02409 } elseif (!empty($name) && isset($this->_templates[$name])) { 02410 $header_html = str_replace('{header}', $header->toHtml(), $this->_templates[$name]); 02411 } else { 02412 $header_html = str_replace('{header}', $header->toHtml(), $this->_headerTemplate); 02413 } 02414 02415 if (isset($this->_advancedElements[$name])){ 02416 $header_html =str_replace('{advancedimg}', $this->_advancedHTML, $header_html); 02417 $elementName='mform_showadvanced'; 02418 if ($this->_showAdvanced==0){ 02419 $buttonlabel = get_string('showadvanced', 'form'); 02420 } else { 02421 $buttonlabel = get_string('hideadvanced', 'form'); 02422 } 02423 $button = '<input name="'.$elementName.'" class="showadvancedbtn" value="'.$buttonlabel.'" type="submit" />'; 02424 $PAGE->requires->js_init_call('M.form.initShowAdvanced', array(), false, moodleform::get_js_module()); 02425 $header_html = str_replace('{button}', $button, $header_html); 02426 } else { 02427 $header_html =str_replace('{advancedimg}', '', $header_html); 02428 $header_html = str_replace('{button}', '', $header_html); 02429 } 02430 02431 if ($this->_fieldsetsOpen > 0) { 02432 $this->_html .= $this->_closeFieldsetTemplate; 02433 $this->_fieldsetsOpen--; 02434 } 02435 02436 $openFieldsetTemplate = str_replace('{id}', $id, $this->_openFieldsetTemplate); 02437 if ($this->_showAdvanced){ 02438 $advclass = ' class="advanced"'; 02439 } else { 02440 $advclass = ' class="advanced hide"'; 02441 } 02442 if (isset($this->_advancedElements[$name])){ 02443 $openFieldsetTemplate = str_replace('{advancedclass}', $advclass, $openFieldsetTemplate); 02444 } else { 02445 $openFieldsetTemplate = str_replace('{advancedclass}', '', $openFieldsetTemplate); 02446 } 02447 $this->_html .= $openFieldsetTemplate . $header_html; 02448 $this->_fieldsetsOpen++; 02449 } // end func renderHeader 02450 02451 function getStopFieldsetElements(){ 02452 return $this->_stopFieldsetElements; 02453 } 02454 } 02455 02460 class MoodleQuickForm_Rule_Required extends HTML_QuickForm_Rule { 02469 function validate($value, $options = null) { 02470 global $CFG; 02471 if (is_array($value) && array_key_exists('text', $value)) { 02472 $value = $value['text']; 02473 } 02474 if (is_array($value)) { 02475 // nasty guess - there has to be something in the array, hopefully nobody invents arrays in arrays 02476 $value = implode('', $value); 02477 } 02478 $stripvalues = array( 02479 '#</?(?!img|canvas|hr).*?>#im', // all tags except img, canvas and hr 02480 '#(\xc2|\xa0|\s| )#', //any whitespaces actually 02481 ); 02482 if (!empty($CFG->strictformsrequired)) { 02483 $value = preg_replace($stripvalues, '', (string)$value); 02484 } 02485 if ((string)$value == '') { 02486 return false; 02487 } 02488 return true; 02489 } 02490 02498 function getValidationScript($format = null) { 02499 global $CFG; 02500 if (!empty($CFG->strictformsrequired)) { 02501 if (!empty($format) && $format == FORMAT_HTML) { 02502 return array('', "{jsVar}.replace(/(<[^img|hr|canvas]+>)| |\s+/ig, '') == ''"); 02503 } else { 02504 return array('', "{jsVar}.replace(/^\s+$/g, '') == ''"); 02505 } 02506 } else { 02507 return array('', "{jsVar} == ''"); 02508 } 02509 } 02510 } 02511 02516 $GLOBALS['_HTML_QuickForm_default_renderer'] = new MoodleQuickForm_Renderer(); 02517 02519 MoodleQuickForm::registerElementType('advcheckbox', "$CFG->libdir/form/advcheckbox.php", 'MoodleQuickForm_advcheckbox'); 02520 MoodleQuickForm::registerElementType('button', "$CFG->libdir/form/button.php", 'MoodleQuickForm_button'); 02521 MoodleQuickForm::registerElementType('cancel', "$CFG->libdir/form/cancel.php", 'MoodleQuickForm_cancel'); 02522 MoodleQuickForm::registerElementType('searchableselector', "$CFG->libdir/form/searchableselector.php", 'MoodleQuickForm_searchableselector'); 02523 MoodleQuickForm::registerElementType('checkbox', "$CFG->libdir/form/checkbox.php", 'MoodleQuickForm_checkbox'); 02524 MoodleQuickForm::registerElementType('date_selector', "$CFG->libdir/form/dateselector.php", 'MoodleQuickForm_date_selector'); 02525 MoodleQuickForm::registerElementType('date_time_selector', "$CFG->libdir/form/datetimeselector.php", 'MoodleQuickForm_date_time_selector'); 02526 MoodleQuickForm::registerElementType('duration', "$CFG->libdir/form/duration.php", 'MoodleQuickForm_duration'); 02527 MoodleQuickForm::registerElementType('editor', "$CFG->libdir/form/editor.php", 'MoodleQuickForm_editor'); 02528 MoodleQuickForm::registerElementType('file', "$CFG->libdir/form/file.php", 'MoodleQuickForm_file'); 02529 MoodleQuickForm::registerElementType('filemanager', "$CFG->libdir/form/filemanager.php", 'MoodleQuickForm_filemanager'); 02530 MoodleQuickForm::registerElementType('filepicker', "$CFG->libdir/form/filepicker.php", 'MoodleQuickForm_filepicker'); 02531 MoodleQuickForm::registerElementType('format', "$CFG->libdir/form/format.php", 'MoodleQuickForm_format'); 02532 MoodleQuickForm::registerElementType('grading', "$CFG->libdir/form/grading.php", 'MoodleQuickForm_grading'); 02533 MoodleQuickForm::registerElementType('group', "$CFG->libdir/form/group.php", 'MoodleQuickForm_group'); 02534 MoodleQuickForm::registerElementType('header', "$CFG->libdir/form/header.php", 'MoodleQuickForm_header'); 02535 MoodleQuickForm::registerElementType('hidden', "$CFG->libdir/form/hidden.php", 'MoodleQuickForm_hidden'); 02536 MoodleQuickForm::registerElementType('htmleditor', "$CFG->libdir/form/htmleditor.php", 'MoodleQuickForm_htmleditor'); 02537 MoodleQuickForm::registerElementType('modgrade', "$CFG->libdir/form/modgrade.php", 'MoodleQuickForm_modgrade'); 02538 MoodleQuickForm::registerElementType('modvisible', "$CFG->libdir/form/modvisible.php", 'MoodleQuickForm_modvisible'); 02539 MoodleQuickForm::registerElementType('password', "$CFG->libdir/form/password.php", 'MoodleQuickForm_password'); 02540 MoodleQuickForm::registerElementType('passwordunmask', "$CFG->libdir/form/passwordunmask.php", 'MoodleQuickForm_passwordunmask'); 02541 MoodleQuickForm::registerElementType('questioncategory', "$CFG->libdir/form/questioncategory.php", 'MoodleQuickForm_questioncategory'); 02542 MoodleQuickForm::registerElementType('radio', "$CFG->libdir/form/radio.php", 'MoodleQuickForm_radio'); 02543 MoodleQuickForm::registerElementType('recaptcha', "$CFG->libdir/form/recaptcha.php", 'MoodleQuickForm_recaptcha'); 02544 MoodleQuickForm::registerElementType('select', "$CFG->libdir/form/select.php", 'MoodleQuickForm_select'); 02545 MoodleQuickForm::registerElementType('selectgroups', "$CFG->libdir/form/selectgroups.php", 'MoodleQuickForm_selectgroups'); 02546 MoodleQuickForm::registerElementType('selectwithlink', "$CFG->libdir/form/selectwithlink.php", 'MoodleQuickForm_selectwithlink'); 02547 MoodleQuickForm::registerElementType('selectyesno', "$CFG->libdir/form/selectyesno.php", 'MoodleQuickForm_selectyesno'); 02548 MoodleQuickForm::registerElementType('static', "$CFG->libdir/form/static.php", 'MoodleQuickForm_static'); 02549 MoodleQuickForm::registerElementType('submit', "$CFG->libdir/form/submit.php", 'MoodleQuickForm_submit'); 02550 MoodleQuickForm::registerElementType('submitlink', "$CFG->libdir/form/submitlink.php", 'MoodleQuickForm_submitlink'); 02551 MoodleQuickForm::registerElementType('tags', "$CFG->libdir/form/tags.php", 'MoodleQuickForm_tags'); 02552 MoodleQuickForm::registerElementType('text', "$CFG->libdir/form/text.php", 'MoodleQuickForm_text'); 02553 MoodleQuickForm::registerElementType('textarea', "$CFG->libdir/form/textarea.php", 'MoodleQuickForm_textarea'); 02554 MoodleQuickForm::registerElementType('url', "$CFG->libdir/form/url.php", 'MoodleQuickForm_url'); 02555 MoodleQuickForm::registerElementType('warning', "$CFG->libdir/form/warning.php", 'MoodleQuickForm_warning'); 02556 02557 MoodleQuickForm::registerRule('required', null, 'MoodleQuickForm_Rule_Required', "$CFG->libdir/formslib.php");