Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/formslib.php
Go to the documentation of this file.
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}&nbsp;</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|&nbsp;)#', //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]+>)|&nbsp;|\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");
 All Data Structures Namespaces Files Functions Variables Enumerations