2009-05-25 08:27:25 +00:00
< ? php
2009-11-01 11:31:16 +00:00
// This file is part of Moodle - http://moodle.org/
//
2009-05-25 08:27:25 +00:00
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
2009-11-01 11:31:16 +00:00
//
2009-05-25 08:27:25 +00:00
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
2006-09-24 17:04:51 +00:00
/**
* formslib . php - library of classes for creating forms in Moodle , based on PEAR QuickForms .
2006-11-12 07:28:13 +00:00
*
* To use formslib then you will want to create a new file purpose_form . php eg . edit_form . php
* and you want to name your class something like { modulename } _ { purpose } _form . Your class will
* extend moodleform overriding abstract classes definition and optionally defintion_after_data
* and validation .
*
* See examples of use of this library in course / edit . php and course / edit_form . php
*
* A few notes :
2010-07-25 13:35:05 +00:00
* form definition is used for both printing of form and processing and should be the same
2006-11-12 07:28:13 +00:00
* for both or you may lose some submitted data which won ' t be let through .
* you should be using setType for every form element except select , radio or checkbox
* elements , these elements clean themselves .
*
*
2010-07-25 13:35:05 +00:00
* @ copyright Jamie Pratt < me @ jamiep . org >
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ package core
* @ subpackage form
2006-09-24 17:04:51 +00:00
*/
2010-07-25 13:35:05 +00:00
defined ( 'MOODLE_INTERNAL' ) || die ();
/** setup.php includes our hacked pear libs first */
2006-09-24 17:04:51 +00:00
require_once 'HTML/QuickForm.php' ;
require_once 'HTML/QuickForm/DHTMLRulesTableless.php' ;
require_once 'HTML/QuickForm/Renderer/Tableless.php' ;
2008-09-21 21:29:41 +00:00
require_once $CFG -> libdir . '/filelib.php' ;
2006-11-09 08:38:40 +00:00
2009-03-30 10:01:39 +00:00
define ( 'EDITOR_UNLIMITED_FILES' , - 1 );
2006-12-19 07:03:08 +00:00
/**
* Callback called when PEAR throws an error
*
* @ param PEAR_Error $error
*/
function pear_handle_error ( $error ){
echo '<strong>' . $error -> GetMessage () . '</strong> ' . $error -> getUserInfo ();
echo '<br /> <strong>Backtrace </strong>:' ;
print_object ( $error -> backtrace );
}
2009-07-02 14:58:41 +00:00
if ( ! empty ( $CFG -> debug ) and $CFG -> debug >= DEBUG_ALL ){
2006-12-19 07:03:08 +00:00
PEAR :: setErrorHandling ( PEAR_ERROR_CALLBACK , 'pear_handle_error' );
2006-09-25 11:08:44 +00:00
}
2009-05-25 08:27:25 +00:00
/**
2009-11-01 11:31:16 +00:00
*
2009-05-25 08:27:25 +00:00
* @ staticvar bool $done
*/
2009-03-13 09:56:53 +00:00
function form_init_date_js () {
ajaxlib/require_js: MDL-16693 $PAGE->requires->... deprecates require_js etc.
There is a new implementation of require_js in lib/deprecatedlib.php,
based on $PAGE->requires.
There were a few other recently introduced functions in lib/weblib.php,
namely print_js_call, print_delayed_js_call, print_js_config and
standard_js_config. These have been removed, since they were never in
a stable branch, and all the places that used them have been changed
to use the newer $PAGE->requires->... methods.
get_require_js_code is also gone, and the evil places that were calling
it, even though it is an internal function, have been fixed.
Also, I made some minor improvements to the code I committed yesterday
for MDL-16695.
All that remains is to update all the places in core code that are
still using require_js.
(This commit also fixes the problem where the admin tree would not
start with the right categories expanded.)
2009-06-12 12:13:07 +00:00
global $PAGE ;
2009-03-13 09:56:53 +00:00
static $done = false ;
if ( ! $done ) {
2009-12-16 20:25:14 +00:00
$PAGE -> requires -> yui2_lib ( 'calendar' );
$PAGE -> requires -> yui2_lib ( 'container' );
ajaxlib/require_js: MDL-16693 $PAGE->requires->... deprecates require_js etc.
There is a new implementation of require_js in lib/deprecatedlib.php,
based on $PAGE->requires.
There were a few other recently introduced functions in lib/weblib.php,
namely print_js_call, print_delayed_js_call, print_js_config and
standard_js_config. These have been removed, since they were never in
a stable branch, and all the places that used them have been changed
to use the newer $PAGE->requires->... methods.
get_require_js_code is also gone, and the evil places that were calling
it, even though it is an internal function, have been fixed.
Also, I made some minor improvements to the code I committed yesterday
for MDL-16695.
All that remains is to update all the places in core code that are
still using require_js.
(This commit also fixes the problem where the admin tree would not
start with the right categories expanded.)
2009-06-12 12:13:07 +00:00
$PAGE -> requires -> js_function_call ( 'init_date_selectors' ,
2010-04-10 17:44:05 +00:00
array ( get_string ( 'firstdayofweek' , 'langconfig' )));
2009-03-13 09:56:53 +00:00
$done = true ;
}
}
2006-12-28 09:32:45 +00:00
2006-11-09 10:42:44 +00:00
/**
2006-11-12 07:28:13 +00:00
* Moodle specific wrapper that separates quickforms syntax from moodle code . You won ' t directly
2007-12-04 10:35:25 +00:00
* use this class you should write a class definition which extends this class or a more specific
2006-11-12 07:28:13 +00:00
* subclass such a moodleform_mod for each form you want to display and / or process with formslib .
*
* You will write your own definition () method which performs the form set up .
2009-05-25 08:27:25 +00:00
*
* @ package moodlecore
* @ copyright Jamie Pratt < me @ jamiep . org >
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
2006-11-09 10:42:44 +00:00
*/
2009-07-16 10:38:15 +00:00
abstract class moodleform {
2009-05-25 08:27:25 +00:00
/** @var string */
2008-07-31 22:15:30 +00:00
protected $_formname ; // form name
2006-11-15 07:40:49 +00:00
/**
* quickform object definition
*
2010-05-18 07:58:45 +00:00
* @ var MoodleQuickForm MoodleQuickForm
2006-11-15 07:40:49 +00:00
*/
2008-07-31 22:15:30 +00:00
protected $_form ;
2006-11-15 07:40:49 +00:00
/**
* globals workaround
*
* @ var array
*/
2008-07-31 22:15:30 +00:00
protected $_customdata ;
2007-08-03 13:08:05 +00:00
/**
* definition_after_data executed flag
2009-05-25 08:27:25 +00:00
* @ var object definition_finalized
2007-08-03 13:08:05 +00:00
*/
2008-07-31 22:15:30 +00:00
protected $_definition_finalized = false ;
2006-11-24 12:20:26 +00:00
2006-11-12 07:28:13 +00:00
/**
* The constructor function calls the abstract function definition () and it will then
* process and clean and attempt to validate incoming data .
*
* It will call your custom validate method to validate data and will also check any rules
* you have specified in definition using addRule
*
* The name of the form ( id attribute of the form ) is automatically generated depending on
* the name you gave the class extending moodleform . You should call your class something
* like
*
2007-08-03 13:08:05 +00:00
* @ param mixed $action the action attribute for the form . If empty defaults to auto detect the
* current url . If a moodle_url object then outputs params as hidden variables .
2006-11-12 07:28:13 +00:00
* @ param array $customdata if your form defintion method needs access to data such as $course
* $cm , etc . to construct the form definition then pass it in this array . You can
* use globals for somethings .
* @ param string $method if you set this to anything other than 'post' then _GET and _POST will
* be merged and used as incoming data to the form .
* @ param string $target target frame for form submission . You will rarely use this . Don ' t use
* it if you don ' t need to as the target attribute is deprecated in xhtml
* strict .
* @ param mixed $attributes you can pass a string of html attributes here or an array .
2009-05-25 08:27:25 +00:00
* @ param bool $editable
* @ return object moodleform
2006-11-12 07:28:13 +00:00
*/
2007-08-03 13:08:05 +00:00
function moodleform ( $action = null , $customdata = null , $method = 'post' , $target = '' , $attributes = null , $editable = true ) {
2006-12-19 07:03:08 +00:00
if ( empty ( $action )){
$action = strip_querystring ( qualified_me ());
}
2006-12-28 09:32:45 +00:00
2007-01-06 20:31:06 +00:00
$this -> _formname = get_class ( $this ); // '_form' suffix kept in order to prevent collisions of form id and other element
2006-10-12 07:33:57 +00:00
$this -> _customdata = $customdata ;
2009-07-02 14:58:41 +00:00
$this -> _form = new MoodleQuickForm ( $this -> _formname , $method , $action , $target , $attributes );
2007-08-03 13:08:05 +00:00
if ( ! $editable ){
$this -> _form -> hardFreeze ();
}
2006-10-12 07:33:57 +00:00
$this -> definition ();
$this -> _form -> addElement ( 'hidden' , 'sesskey' , null ); // automatic sesskey protection
2009-09-26 17:07:08 +00:00
$this -> _form -> setType ( 'sesskey' , PARAM_RAW );
2006-10-12 07:33:57 +00:00
$this -> _form -> setDefault ( 'sesskey' , sesskey ());
2006-10-14 12:32:31 +00:00
$this -> _form -> addElement ( 'hidden' , '_qf__' . $this -> _formname , null ); // form submission marker
2009-09-26 17:07:08 +00:00
$this -> _form -> setType ( '_qf__' . $this -> _formname , PARAM_RAW );
2006-10-14 12:32:31 +00:00
$this -> _form -> setDefault ( '_qf__' . $this -> _formname , 1 );
$this -> _form -> _setDefaultRuleMessages ();
2006-10-12 07:33:57 +00:00
// we have to know all input types before processing submission ;-)
$this -> _process_submission ( $method );
}
2006-11-09 10:42:44 +00:00
2006-10-24 11:05:50 +00:00
/**
2006-11-12 07:28:13 +00:00
* To autofocus on first form element or first element with error .
2006-10-24 11:05:50 +00:00
*
2007-03-16 01:46:17 +00:00
* @ param string $name if this is set then the focus is forced to a field with this name
*
2006-10-24 11:05:50 +00:00
* @ return string javascript to select form element with first error or
2006-11-12 07:28:13 +00:00
* first element if no errors . Use this as a parameter
* when calling print_header
2006-10-24 11:05:50 +00:00
*/
2007-11-12 17:12:35 +00:00
function focus ( $name = NULL ) {
2006-11-22 15:58:07 +00:00
$form =& $this -> _form ;
2007-11-12 17:12:35 +00:00
$elkeys = array_keys ( $form -> _elementIndex );
$error = false ;
2006-11-22 15:58:07 +00:00
if ( isset ( $form -> _errors ) && 0 != count ( $form -> _errors )){
$errorkeys = array_keys ( $form -> _errors );
$elkeys = array_intersect ( $elkeys , $errorkeys );
2007-11-12 17:12:35 +00:00
$error = true ;
2006-10-24 11:05:50 +00:00
}
2007-11-12 17:12:35 +00:00
if ( $error or empty ( $name )) {
$names = array ();
while ( empty ( $names ) and ! empty ( $elkeys )) {
$el = array_shift ( $elkeys );
$names = $form -> _getElNamesRecursive ( $el );
}
if ( ! empty ( $names )) {
$name = array_shift ( $names );
}
2007-03-16 01:46:17 +00:00
}
2007-11-12 17:12:35 +00:00
$focus = '' ;
if ( ! empty ( $name )) {
$focus = 'forms[\'' . $form -> getAttribute ( 'id' ) . '\'].elements[\'' . $name . '\']' ;
2006-11-22 15:58:07 +00:00
}
2007-11-12 17:12:35 +00:00
2006-11-22 15:58:07 +00:00
return $focus ;
}
2006-10-12 07:33:57 +00:00
2006-11-09 10:42:44 +00:00
/**
* Internal method . Alters submitted data to be suitable for quickforms processing .
* Must be called when the form is fully set up .
2009-05-25 08:27:25 +00:00
*
* @ param string $method
2006-11-09 10:42:44 +00:00
*/
2006-10-12 07:33:57 +00:00
function _process_submission ( $method ) {
$submission = array ();
if ( $method == 'post' ) {
if ( ! empty ( $_POST )) {
$submission = $_POST ;
}
} else {
$submission = array_merge_recursive ( $_GET , $_POST ); // emulate handling of parameters in xxxx_param()
}
// following trick is needed to enable proper sesskey checks when using GET forms
2006-10-14 12:32:31 +00:00
// the _qf__.$this->_formname serves as a marker that form was actually submitted
if ( array_key_exists ( '_qf__' . $this -> _formname , $submission ) and $submission [ '_qf__' . $this -> _formname ] == 1 ) {
2006-10-12 07:33:57 +00:00
if ( ! confirm_sesskey ()) {
2008-09-08 02:35:22 +00:00
print_error ( 'invalidsesskey' );
2006-10-12 07:33:57 +00:00
}
2006-11-09 10:42:44 +00:00
$files = $_FILES ;
2006-10-12 07:33:57 +00:00
} else {
$submission = array ();
2006-11-09 10:42:44 +00:00
$files = array ();
2006-10-12 07:33:57 +00:00
}
2006-11-09 10:42:44 +00:00
$this -> _form -> updateSubmission ( $submission , $files );
2006-10-12 07:33:57 +00:00
}
2006-11-09 10:42:44 +00:00
/**
2010-07-14 08:40:48 +00:00
* Internal method . Validates all old - style deprecated uploaded files .
* The new way is to upload files via repository api .
2009-11-01 11:31:16 +00:00
*
2009-05-25 08:27:25 +00:00
* @ global object
* @ global object
* @ param array $files
* @ return bool | array Success or an array of errors
2006-11-09 10:42:44 +00:00
*/
2007-09-26 19:25:50 +00:00
function _validate_files ( & $files ) {
2008-07-31 22:15:30 +00:00
global $CFG , $COURSE ;
2007-09-26 19:25:50 +00:00
$files = array ();
2006-11-09 08:38:40 +00:00
if ( empty ( $_FILES )) {
// we do not need to do any checks because no files were submitted
2007-09-26 19:25:50 +00:00
// note: server side rules do not work for files - use custom verification in validate() instead
2006-11-09 08:38:40 +00:00
return true ;
}
2008-07-31 22:15:30 +00:00
$errors = array ();
$filenames = array ();
2006-11-09 08:38:40 +00:00
// now check that we really want each file
foreach ( $_FILES as $elname => $file ) {
2008-07-31 22:15:30 +00:00
$required = $this -> _form -> isElementRequired ( $elname );
2007-09-26 19:25:50 +00:00
2008-07-31 22:15:30 +00:00
if ( $file [ 'error' ] == 4 and $file [ 'size' ] == 0 ) {
if ( $required ) {
$errors [ $elname ] = get_string ( 'required' );
2006-11-09 08:38:40 +00:00
}
2008-07-31 22:15:30 +00:00
unset ( $_FILES [ $elname ]);
continue ;
}
2008-09-21 21:29:41 +00:00
if ( ! empty ( $file [ 'error' ])) {
$errors [ $elname ] = file_get_upload_error ( $file [ 'error' ]);
2008-07-31 22:15:30 +00:00
unset ( $_FILES [ $elname ]);
continue ;
}
if ( ! is_uploaded_file ( $file [ 'tmp_name' ])) {
// TODO: improve error message
$errors [ $elname ] = get_string ( 'error' );
unset ( $_FILES [ $elname ]);
continue ;
}
if ( ! $this -> _form -> elementExists ( $elname ) or ! $this -> _form -> getElementType ( $elname ) == 'file' ) {
// hmm, this file was not requested
unset ( $_FILES [ $elname ]);
continue ;
}
/*
2010-07-14 08:40:48 +00:00
// TODO: rethink the file scanning MDL-19380
2008-07-31 22:15:30 +00:00
if ( $CFG -> runclamonupload ) {
if ( ! clam_scan_moodle_file ( $_FILES [ $elname ], $COURSE )) {
$errors [ $elname ] = $_FILES [ $elname ][ 'uploadlog' ];
unset ( $_FILES [ $elname ]);
continue ;
}
}
*/
$filename = clean_param ( $_FILES [ $elname ][ 'name' ], PARAM_FILE );
if ( $filename === '' ) {
// TODO: improve error message - wrong chars
$errors [ $elname ] = get_string ( 'error' );
unset ( $_FILES [ $elname ]);
continue ;
2006-11-09 08:38:40 +00:00
}
2008-07-31 22:15:30 +00:00
if ( in_array ( $filename , $filenames )) {
// TODO: improve error message - duplicate name
$errors [ $elname ] = get_string ( 'error' );
unset ( $_FILES [ $elname ]);
continue ;
}
$filenames [] = $filename ;
$_FILES [ $elname ][ 'name' ] = $filename ;
$files [ $elname ] = $_FILES [ $elname ][ 'tmp_name' ];
2006-11-09 08:38:40 +00:00
}
// return errors if found
2008-07-31 22:15:30 +00:00
if ( count ( $errors ) == 0 ){
2006-11-09 08:38:40 +00:00
return true ;
2007-09-26 19:25:50 +00:00
2006-11-09 08:38:40 +00:00
} else {
2007-09-26 19:25:50 +00:00
$files = array ();
2006-11-09 08:38:40 +00:00
return $errors ;
}
}
2006-11-09 10:42:44 +00:00
/**
2006-11-12 07:28:13 +00:00
* Load in existing data as form defaults . Usually new entry defaults are stored directly in
* form definition ( new entry form ); this function is used to load in data where values
* already exist and data is being edited ( edit entry form ) .
2006-11-09 10:42:44 +00:00
*
2008-06-09 16:53:30 +00:00
* note : $slashed param removed
*
2006-11-09 10:42:44 +00:00
* @ param mixed $default_values object or array of default values
*/
2008-06-09 16:53:30 +00:00
function set_data ( $default_values ) {
2006-10-12 07:33:57 +00:00
if ( is_object ( $default_values )) {
$default_values = ( array ) $default_values ;
}
2008-06-09 16:53:30 +00:00
$this -> _form -> setDefaults ( $default_values );
2006-10-12 07:33:57 +00:00
}
2009-05-25 08:27:25 +00:00
/**
2010-07-14 08:40:48 +00:00
* @ deprecated
2009-05-25 08:27:25 +00:00
*/
2006-12-28 21:21:44 +00:00
function set_upload_manager ( $um = false ) {
2010-07-14 08:40:48 +00:00
debugging ( 'Old file uploads can not be used any more, please use new filepicker element' );
2006-11-23 08:24:58 +00:00
}
2006-11-09 10:42:44 +00:00
/**
* Check that form was submitted . Does not check validity of submitted data .
*
* @ return bool true if form properly submitted
*/
2006-10-12 07:33:57 +00:00
function is_submitted () {
return $this -> _form -> isSubmitted ();
}
2009-05-25 08:27:25 +00:00
/**
* @ staticvar bool $nosubmit
*/
2006-12-19 07:03:08 +00:00
function no_submit_button_pressed (){
static $nosubmit = null ; // one check is enough
if ( ! is_null ( $nosubmit )){
return $nosubmit ;
}
$mform =& $this -> _form ;
$nosubmit = false ;
2006-12-28 09:32:45 +00:00
if ( ! $this -> is_submitted ()){
return false ;
}
2006-12-19 07:03:08 +00:00
foreach ( $mform -> _noSubmitButtons as $nosubmitbutton ){
if ( optional_param ( $nosubmitbutton , 0 , PARAM_RAW )){
$nosubmit = true ;
break ;
}
}
return $nosubmit ;
}
2006-11-09 10:42:44 +00:00
/**
* Check that form data is valid .
2009-06-02 10:39:21 +00:00
* You should almost always use this , rather than { @ see validate_defined_fields }
2006-11-09 10:42:44 +00:00
*
2009-05-25 08:27:25 +00:00
* @ staticvar bool $validated
2006-11-09 10:42:44 +00:00
* @ return bool true if form data valid
*/
2006-10-12 07:33:57 +00:00
function is_validated () {
2007-08-03 13:08:05 +00:00
//finalize the form definition before any processing
if ( ! $this -> _definition_finalized ) {
$this -> _definition_finalized = true ;
$this -> definition_after_data ();
}
2009-06-02 10:39:21 +00:00
return $this -> validate_defined_fields ();
}
/**
* Validate the form .
*
* You almost always want to call { @ see is_validated } instead of this
* because it calls { @ see definition_after_data } first , before validating the form ,
* which is what you want in 99 % of cases .
*
* This is provided as a separate function for those special cases where
* you want the form validated before definition_after_data is called
* for example , to selectively add new elements depending on a no_submit_button press ,
* but only when the form is valid when the no_submit_button is pressed ,
*
* @ param boolean $validateonnosubmit optional , defaults to false . The default behaviour
* is NOT to validate the form when a no submit button has been pressed .
* pass true here to override this behaviour
*
* @ return bool true if form data valid
*/
function validate_defined_fields ( $validateonnosubmit = false ) {
static $validated = null ; // one validation is enough
$mform =& $this -> _form ;
if ( $this -> no_submit_button_pressed () && empty ( $validateonnosubmit )){
2007-01-10 05:05:26 +00:00
return false ;
} elseif ( $validated === null ) {
2006-12-04 10:55:50 +00:00
$internal_val = $mform -> validate ();
2007-09-26 19:25:50 +00:00
$files = array ();
$file_val = $this -> _validate_files ( $files );
if ( $file_val !== true ) {
if ( ! empty ( $file_val )) {
foreach ( $file_val as $element => $msg ) {
$mform -> setElementError ( $element , $msg );
}
}
$file_val = false ;
}
2008-09-07 13:30:46 +00:00
$data = $mform -> exportValues ();
2007-09-26 19:25:50 +00:00
$moodle_val = $this -> validation ( $data , $files );
2007-11-23 22:15:07 +00:00
if (( is_array ( $moodle_val ) && count ( $moodle_val ) !== 0 )) {
// non-empty array means errors
foreach ( $moodle_val as $element => $msg ) {
$mform -> setElementError ( $element , $msg );
2006-10-12 07:33:57 +00:00
}
2007-11-23 22:15:07 +00:00
$moodle_val = false ;
} else {
// anything else means validation ok
$moodle_val = true ;
2006-10-12 07:33:57 +00:00
}
2007-09-26 19:25:50 +00:00
2006-11-09 08:38:40 +00:00
$validated = ( $internal_val and $moodle_val and $file_val );
2006-10-12 07:33:57 +00:00
}
2007-01-10 05:05:26 +00:00
return $validated ;
2006-10-12 07:33:57 +00:00
}
2006-12-04 09:36:30 +00:00
/**
* Return true if a cancel button has been pressed resulting in the form being submitted .
*
* @ return boolean true if a cancel button has been pressed
*/
function is_cancelled (){
$mform =& $this -> _form ;
2006-12-19 07:03:08 +00:00
if ( $mform -> isSubmitted ()){
foreach ( $mform -> _cancelButtons as $cancelbutton ){
if ( optional_param ( $cancelbutton , 0 , PARAM_RAW )){
return true ;
}
2006-12-04 09:36:30 +00:00
}
}
return false ;
}
2006-11-09 10:42:44 +00:00
/**
2006-11-12 07:28:13 +00:00
* Return submitted data if properly submitted or returns NULL if validation fails or
* if there is no submitted data .
2008-07-31 22:15:30 +00:00
*
2008-06-09 16:53:30 +00:00
* note : $slashed param removed
2006-11-09 10:42:44 +00:00
*
* @ return object submitted data ; NULL if not valid or not submitted
*/
2008-06-09 16:53:30 +00:00
function get_data () {
2006-12-04 09:36:30 +00:00
$mform =& $this -> _form ;
2006-12-04 10:55:50 +00:00
2006-10-12 07:33:57 +00:00
if ( $this -> is_submitted () and $this -> is_validated ()) {
2008-06-09 16:53:30 +00:00
$data = $mform -> exportValues ();
2006-10-14 12:32:31 +00:00
unset ( $data [ 'sesskey' ]); // we do not need to return sesskey
unset ( $data [ '_qf__' . $this -> _formname ]); // we do not need the submission marker too
2006-10-12 07:33:57 +00:00
if ( empty ( $data )) {
return NULL ;
} else {
return ( object ) $data ;
}
} else {
return NULL ;
}
}
2007-08-03 13:08:05 +00:00
/**
* Return submitted data without validation or NULL if there is no submitted data .
2008-06-09 16:53:30 +00:00
* note : $slashed param removed
2007-08-03 13:08:05 +00:00
*
* @ return object submitted data ; NULL if not submitted
*/
2008-06-09 16:53:30 +00:00
function get_submitted_data () {
2007-08-03 13:08:05 +00:00
$mform =& $this -> _form ;
if ( $this -> is_submitted ()) {
2008-06-09 16:53:30 +00:00
$data = $mform -> exportValues ();
2007-08-03 13:08:05 +00:00
unset ( $data [ 'sesskey' ]); // we do not need to return sesskey
unset ( $data [ '_qf__' . $this -> _formname ]); // we do not need the submission marker too
if ( empty ( $data )) {
return NULL ;
} else {
return ( object ) $data ;
}
} else {
return NULL ;
}
}
2006-11-09 10:42:44 +00:00
/**
* Save verified uploaded files into directory . Upload process can be customised from definition ()
2008-07-31 22:15:30 +00:00
* NOTE : please use save_stored_file () or save_file ()
2009-05-25 08:27:25 +00:00
*
* @ return bool Always false
2006-11-09 10:42:44 +00:00
*/
2006-11-09 08:38:40 +00:00
function save_files ( $destination ) {
2008-07-31 22:15:30 +00:00
debugging ( 'Not used anymore, please fix code! Use save_stored_file() or save_file() instead' );
2006-11-09 08:38:40 +00:00
return false ;
}
2006-11-07 08:48:18 +00:00
2006-12-28 21:21:44 +00:00
/**
2008-07-31 22:15:30 +00:00
* Returns name of uploaded file .
2009-05-25 08:27:25 +00:00
*
* @ global object
2008-07-31 22:15:30 +00:00
* @ param string $elname , first element if null
2006-12-28 21:21:44 +00:00
* @ return mixed false in case of failure , string if ok
*/
2008-07-31 22:15:30 +00:00
function get_new_filename ( $elname = null ) {
2008-09-07 13:30:46 +00:00
global $USER ;
2008-07-31 22:15:30 +00:00
if ( ! $this -> is_submitted () or ! $this -> is_validated ()) {
return false ;
}
if ( is_null ( $elname )) {
if ( empty ( $_FILES )) {
return false ;
}
reset ( $_FILES );
$elname = key ( $_FILES );
}
2008-09-07 13:30:46 +00:00
if ( empty ( $elname )) {
return false ;
}
$element = $this -> _form -> getElement ( $elname );
2010-06-08 03:09:14 +00:00
if ( $element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager ) {
2008-09-07 13:30:46 +00:00
$values = $this -> _form -> exportValues ( $elname );
if ( empty ( $values [ $elname ])) {
return false ;
}
$draftid = $values [ $elname ];
$fs = get_file_storage ();
$context = get_context_instance ( CONTEXT_USER , $USER -> id );
2010-07-03 13:37:13 +00:00
if ( ! $files = $fs -> get_area_files ( $context -> id , 'user' , 'draft' , $draftid , 'id DESC' , false )) {
2008-09-07 13:30:46 +00:00
return false ;
}
$file = reset ( $files );
return $file -> get_filename ();
}
2008-07-31 22:15:30 +00:00
if ( ! isset ( $_FILES [ $elname ])) {
return false ;
}
return $_FILES [ $elname ][ 'name' ];
2006-12-28 21:21:44 +00:00
}
2007-09-26 16:53:26 +00:00
/**
2008-07-31 22:15:30 +00:00
* Save file to standard filesystem
2009-05-25 08:27:25 +00:00
*
* @ global object
2008-07-31 22:15:30 +00:00
* @ param string $elname name of element
* @ param string $pathname full path name of file
* @ param bool $override override file if exists
* @ return bool success
2007-09-26 16:53:26 +00:00
*/
2008-07-31 22:15:30 +00:00
function save_file ( $elname , $pathname , $override = false ) {
2008-09-07 13:30:46 +00:00
global $USER ;
2007-09-26 16:53:26 +00:00
2008-09-07 13:30:46 +00:00
if ( ! $this -> is_submitted () or ! $this -> is_validated ()) {
2007-09-26 16:53:26 +00:00
return false ;
}
2008-07-31 22:15:30 +00:00
if ( file_exists ( $pathname )) {
if ( $override ) {
if ( !@ unlink ( $pathname )) {
return false ;
}
} else {
return false ;
}
}
2008-09-07 13:30:46 +00:00
$element = $this -> _form -> getElement ( $elname );
2010-06-08 03:09:14 +00:00
if ( $element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager ) {
2008-09-07 13:30:46 +00:00
$values = $this -> _form -> exportValues ( $elname );
if ( empty ( $values [ $elname ])) {
return false ;
}
$draftid = $values [ $elname ];
$fs = get_file_storage ();
$context = get_context_instance ( CONTEXT_USER , $USER -> id );
2010-07-03 13:37:13 +00:00
if ( ! $files = $fs -> get_area_files ( $context -> id , 'user' , 'draft' , $draftid , 'id DESC' , false )) {
2008-09-07 13:30:46 +00:00
return false ;
}
$file = reset ( $files );
return $file -> copy_content_to ( $pathname );
} else if ( isset ( $_FILES [ $elname ])) {
return copy ( $_FILES [ $elname ][ 'tmp_name' ], $pathname );
2008-07-31 22:15:30 +00:00
}
2008-09-07 13:30:46 +00:00
return false ;
2008-07-31 22:15:30 +00:00
}
2010-07-11 11:43:15 +00:00
/**
* Returns a temporary file , do not forget to delete after not needed any more .
*
* @ param string $elname
* @ return string or false
*/
function save_temp_file ( $elname ) {
if ( ! $this -> get_new_filename ( $elname )) {
return false ;
}
if ( ! $dir = make_upload_directory ( 'temp/forms' )) {
return false ;
}
if ( ! $tempfile = tempnam ( $dir , 'tempup_' )) {
return false ;
}
if ( ! $this -> save_file ( $elname , $tempfile , true )) {
// something went wrong
@ unlink ( $tempfile );
return false ;
}
return $tempfile ;
}
2010-06-08 03:09:14 +00:00
/**
2010-06-10 09:58:45 +00:00
* Get draft files of a form element
* This is a protected method which will be used only inside moodleforms
*
* @ global object $USER
* @ param string $elname name of element
* @ return array
*/
protected function get_draft_files ( $elname ) {
global $USER ;
if ( ! $this -> is_submitted ()) {
return false ;
}
$element = $this -> _form -> getElement ( $elname );
if ( $element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager ) {
$values = $this -> _form -> exportValues ( $elname );
if ( empty ( $values [ $elname ])) {
return false ;
}
$draftid = $values [ $elname ];
$fs = get_file_storage ();
$context = get_context_instance ( CONTEXT_USER , $USER -> id );
2010-07-03 13:37:13 +00:00
if ( ! $files = $fs -> get_area_files ( $context -> id , 'user' , 'draft' , $draftid , 'id DESC' , false )) {
2010-06-10 09:58:45 +00:00
return null ;
}
return $files ;
}
return null ;
}
2008-07-31 22:15:30 +00:00
/**
* Save file to local filesystem pool
2009-05-25 08:27:25 +00:00
*
* @ global object
2008-07-31 22:15:30 +00:00
* @ param string $elname name of element
2008-09-02 09:46:29 +00:00
* @ param int $newcontextid
* @ param string $newfilearea
* @ param string $newfilepath
* @ param string $newfilename - use specified filename , if not specified name of uploaded file used
2008-09-03 05:14:24 +00:00
* @ param bool $overwrite - overwrite file if exists
2008-09-02 09:46:29 +00:00
* @ param int $newuserid - new userid if required
2008-07-31 22:15:30 +00:00
* @ return mixed stored_file object or false if error ; may throw exception if duplicate found
*/
2010-07-03 13:37:13 +00:00
function save_stored_file ( $elname , $newcontextid , $newcomponent , $newfilearea , $newitemid , $newfilepath = '/' ,
2008-09-03 05:14:24 +00:00
$newfilename = null , $overwrite = false , $newuserid = null ) {
2008-09-02 09:46:29 +00:00
global $USER ;
2008-07-31 22:15:30 +00:00
if ( ! $this -> is_submitted () or ! $this -> is_validated ()) {
2007-09-26 19:25:50 +00:00
return false ;
2008-07-31 22:15:30 +00:00
}
2007-09-26 19:25:50 +00:00
2008-09-02 09:46:29 +00:00
if ( empty ( $newuserid )) {
$newuserid = $USER -> id ;
2007-09-26 19:25:50 +00:00
}
2007-09-26 16:53:26 +00:00
2008-09-07 13:30:46 +00:00
$element = $this -> _form -> getElement ( $elname );
$fs = get_file_storage ();
2008-07-31 22:15:30 +00:00
2008-09-07 13:30:46 +00:00
if ( $element instanceof MoodleQuickForm_filepicker ) {
$values = $this -> _form -> exportValues ( $elname );
if ( empty ( $values [ $elname ])) {
return false ;
}
$draftid = $values [ $elname ];
$context = get_context_instance ( CONTEXT_USER , $USER -> id );
2010-07-03 13:37:13 +00:00
if ( ! $files = $fs -> get_area_files ( $context -> id , 'user' , 'draft' , $draftid , 'id DESC' , false )) {
2008-09-07 13:30:46 +00:00
return false ;
}
$file = reset ( $files );
if ( is_null ( $newfilename )) {
$newfilename = $file -> get_filename ();
}
2008-07-31 22:15:30 +00:00
2008-09-07 13:30:46 +00:00
if ( $overwrite ) {
2010-07-03 13:37:13 +00:00
if ( $oldfile = $fs -> get_file ( $newcontextid , $newcomponent , $newfilearea , $newitemid , $newfilepath , $newfilename )) {
2008-09-07 13:30:46 +00:00
if ( ! $oldfile -> delete ()) {
return false ;
}
2008-09-02 09:46:29 +00:00
}
}
2010-07-03 13:37:13 +00:00
$file_record = array ( 'contextid' => $newcontextid , 'component' => $newcomponent , 'filearea' => $newfilearea , 'itemid' => $newitemid ,
2008-09-07 13:30:46 +00:00
'filepath' => $newfilepath , 'filename' => $newfilename , 'userid' => $newuserid );
return $fs -> create_file_from_storedfile ( $file_record , $file );
2008-09-02 09:46:29 +00:00
2008-09-07 13:30:46 +00:00
} else if ( isset ( $_FILES [ $elname ])) {
$filename = is_null ( $newfilename ) ? $_FILES [ $elname ][ 'name' ] : $newfilename ;
2008-07-31 22:15:30 +00:00
2008-09-07 13:30:46 +00:00
if ( $overwrite ) {
2010-07-03 13:37:13 +00:00
if ( $oldfile = $fs -> get_file ( $newcontextid , $newcomponent , $newfilearea , $newitemid , $newfilepath , $newfilename )) {
2008-09-07 13:30:46 +00:00
if ( ! $oldfile -> delete ()) {
return false ;
}
}
2008-09-02 09:46:29 +00:00
}
2008-09-07 13:30:46 +00:00
2010-07-03 13:37:13 +00:00
$file_record = array ( 'contextid' => $newcontextid , 'component' => $newcomponent , 'filearea' => $newfilearea , 'itemid' => $newitemid ,
2008-09-07 13:30:46 +00:00
'filepath' => $newfilepath , 'filename' => $newfilename , 'userid' => $newuserid );
return $fs -> create_file_from_pathname ( $file_record , $_FILES [ $elname ][ 'tmp_name' ]);
2008-09-02 09:46:29 +00:00
}
return false ;
2008-07-31 22:15:30 +00:00
}
/**
* Get content of uploaded file .
2009-05-25 08:27:25 +00:00
*
* @ global object
2008-07-31 22:15:30 +00:00
* @ param $element name of file upload element
* @ return mixed false in case of failure , string if ok
*/
function get_file_content ( $elname ) {
2008-09-07 13:30:46 +00:00
global $USER ;
2008-07-31 22:15:30 +00:00
if ( ! $this -> is_submitted () or ! $this -> is_validated ()) {
return false ;
}
2008-09-07 13:30:46 +00:00
$element = $this -> _form -> getElement ( $elname );
2010-06-08 03:09:14 +00:00
if ( $element instanceof MoodleQuickForm_filepicker || $element instanceof MoodleQuickForm_filemanager ) {
2008-09-07 13:30:46 +00:00
$values = $this -> _form -> exportValues ( $elname );
if ( empty ( $values [ $elname ])) {
return false ;
}
$draftid = $values [ $elname ];
$fs = get_file_storage ();
$context = get_context_instance ( CONTEXT_USER , $USER -> id );
2010-07-03 13:37:13 +00:00
if ( ! $files = $fs -> get_area_files ( $context -> id , 'user' , 'draft' , $draftid , 'id DESC' , false )) {
2008-09-07 13:30:46 +00:00
return false ;
}
$file = reset ( $files );
return $file -> get_content ();
} else if ( isset ( $_FILES [ $elname ])) {
return file_get_contents ( $_FILES [ $elname ][ 'tmp_name' ]);
2007-09-26 16:53:26 +00:00
}
2008-07-31 22:15:30 +00:00
2008-09-07 13:30:46 +00:00
return false ;
2007-09-26 16:53:26 +00:00
}
2006-11-09 10:42:44 +00:00
/**
* Print html form .
*/
2006-10-12 07:33:57 +00:00
function display () {
2007-08-03 13:08:05 +00:00
//finalize the form definition if not yet done
if ( ! $this -> _definition_finalized ) {
$this -> _definition_finalized = true ;
$this -> definition_after_data ();
}
2006-10-12 07:33:57 +00:00
$this -> _form -> display ();
}
2006-11-09 08:38:40 +00:00
/**
2006-11-09 10:42:44 +00:00
* Abstract method - always override !
2006-11-09 08:38:40 +00:00
*/
2009-07-16 10:38:15 +00:00
protected abstract function definition ();
2006-10-24 11:05:50 +00:00
2006-10-16 12:07:44 +00:00
/**
2006-11-09 10:42:44 +00:00
* Dummy stub method - override if you need to setup the form depending on current
2007-01-12 18:52:09 +00:00
* values . This method is called after definition (), data submission and set_data () .
2006-11-09 10:42:44 +00:00
* All form setup that is dependent on form values should go in here .
2006-10-16 12:07:44 +00:00
*/
function definition_after_data (){
}
2006-10-12 07:33:57 +00:00
2006-11-09 10:42:44 +00:00
/**
* Dummy stub method - override if you needed to perform some extra validation .
* If there are errors return array of errors ( " fieldname " => " error message " ),
* otherwise true if ok .
2006-11-09 10:43:26 +00:00
*
2007-09-26 19:25:50 +00:00
* Server side rules do not work for uploaded files , implement serverside rules here if needed .
*
2006-11-09 10:42:44 +00:00
* @ param array $data array of ( " fieldname " => value ) of submitted data
2007-09-26 19:25:50 +00:00
* @ param array $files array of uploaded files " element_name " => tmp_file_path
2007-11-23 22:15:07 +00:00
* @ return array of " element_name " => " error_description " if there are errors ,
* or an empty array if everything is OK ( true allowed for backwards compatibility too ) .
2006-11-09 10:42:44 +00:00
*/
2007-09-26 19:25:50 +00:00
function validation ( $data , $files ) {
2007-11-20 15:08:05 +00:00
return array ();
2006-10-12 07:33:57 +00:00
}
2006-11-24 12:20:26 +00:00
2006-11-24 12:33:53 +00:00
/**
* Method to add a repeating group of elements to a form .
*
* @ param array $elementobjs Array of elements or groups of elements that are to be repeated
* @ param integer $repeats no of times to repeat elements initially
* @ param array $options Array of options to apply to elements . Array keys are element names .
* This is an array of arrays . The second sets of keys are the option types
* for the elements :
* 'default' - default value is value
* 'type' - PARAM_ * constant is value
* 'helpbutton' - helpbutton params array is value
* 'disabledif' - last three moodleform :: disabledIf ()
* params are value as an array
* @ param string $repeathiddenname name for hidden element storing no of repeats in this form
* @ param string $addfieldsname name for button to add more fields
* @ param int $addfieldsno how many fields to add at a time
2007-01-07 12:46:47 +00:00
* @ param string $addstring name of button , { no } is replaced by no of blanks that will be added .
2007-10-09 15:44:06 +00:00
* @ param boolean $addbuttoninside if true , don ' t call closeHeaderBefore ( $addfieldsname ) . Default false .
2006-12-19 07:03:08 +00:00
* @ return int no of repeats of element in this page
2006-11-24 12:33:53 +00:00
*/
2007-10-09 15:44:06 +00:00
function repeat_elements ( $elementobjs , $repeats , $options , $repeathiddenname ,
$addfieldsname , $addfieldsno = 5 , $addstring = null , $addbuttoninside = false ){
2007-01-07 12:46:47 +00:00
if ( $addstring === null ){
$addstring = get_string ( 'addfields' , 'form' , $addfieldsno );
} else {
$addstring = str_ireplace ( '{no}' , $addfieldsno , $addstring );
}
2006-11-24 12:20:26 +00:00
$repeats = optional_param ( $repeathiddenname , $repeats , PARAM_INT );
$addfields = optional_param ( $addfieldsname , '' , PARAM_TEXT );
if ( ! empty ( $addfields )){
$repeats += $addfieldsno ;
}
$mform =& $this -> _form ;
2006-12-19 07:03:08 +00:00
$mform -> registerNoSubmitButton ( $addfieldsname );
2006-11-24 12:20:26 +00:00
$mform -> addElement ( 'hidden' , $repeathiddenname , $repeats );
2009-09-26 17:07:08 +00:00
$mform -> setType ( $repeathiddenname , PARAM_INT );
2006-11-24 12:20:26 +00:00
//value not to be overridden by submitted value
$mform -> setConstants ( array ( $repeathiddenname => $repeats ));
2009-03-18 07:08:18 +00:00
$namecloned = array ();
for ( $i = 0 ; $i < $repeats ; $i ++ ) {
2006-11-24 12:20:26 +00:00
foreach ( $elementobjs as $elementobj ){
2008-10-13 11:52:35 +00:00
$elementclone = fullclone ( $elementobj );
2007-01-18 11:21:10 +00:00
$name = $elementclone -> getName ();
2009-03-18 07:08:18 +00:00
$namecloned [] = $name ;
if ( ! empty ( $name )) {
2007-01-08 15:53:17 +00:00
$elementclone -> setName ( $name . " [ $i ] " );
}
2009-03-18 07:08:18 +00:00
if ( is_a ( $elementclone , 'HTML_QuickForm_header' )) {
$value = $elementclone -> _text ;
2007-01-07 12:46:47 +00:00
$elementclone -> setValue ( str_replace ( '{no}' , ( $i + 1 ), $value ));
} else {
$value = $elementclone -> getLabel ();
$elementclone -> setLabel ( str_replace ( '{no}' , ( $i + 1 ), $value ));
2006-11-24 12:20:26 +00:00
}
2007-01-18 11:21:10 +00:00
2006-11-24 12:20:26 +00:00
$mform -> addElement ( $elementclone );
}
}
for ( $i = 0 ; $i < $repeats ; $i ++ ) {
foreach ( $options as $elementname => $elementoptions ){
$pos = strpos ( $elementname , '[' );
if ( $pos !== FALSE ){
$realelementname = substr ( $elementname , 0 , $pos + 1 ) . " [ $i ] " ;
$realelementname .= substr ( $elementname , $pos + 1 );
} else {
$realelementname = $elementname . " [ $i ] " ;
}
foreach ( $elementoptions as $option => $params ){
switch ( $option ){
case 'default' :
$mform -> setDefault ( $realelementname , $params );
break ;
case 'helpbutton' :
2010-07-28 11:04:35 +00:00
$mform -> addHelpButton ( $realelementname , $params );
2006-11-24 12:20:26 +00:00
break ;
case 'disabledif' :
2009-03-18 07:08:18 +00:00
foreach ( $namecloned as $num => $name ){
if ( $params [ 0 ] == $name ){
$params [ 0 ] = $params [ 0 ] . " [ $i ] " ;
break ;
}
}
2007-01-10 05:05:26 +00:00
$params = array_merge ( array ( $realelementname ), $params );
call_user_func_array ( array ( & $mform , 'disabledIf' ), $params );
break ;
case 'rule' :
if ( is_string ( $params )){
$params = array ( null , $params , null , 'client' );
}
$params = array_merge ( array ( $realelementname ), $params );
call_user_func_array ( array ( & $mform , 'addRule' ), $params );
2006-11-24 12:20:26 +00:00
break ;
}
}
}
}
2007-01-07 12:46:47 +00:00
$mform -> addElement ( 'submit' , $addfieldsname , $addstring );
2006-12-19 07:03:08 +00:00
2007-10-09 15:44:06 +00:00
if ( ! $addbuttoninside ) {
$mform -> closeHeaderBefore ( $addfieldsname );
}
2006-11-24 12:20:26 +00:00
2006-12-14 12:44:10 +00:00
return $repeats ;
2006-11-24 12:20:26 +00:00
}
2007-12-04 10:35:25 +00:00
/**
* Adds a link / button that controls the checked state of a group of checkboxes .
2009-05-25 08:27:25 +00:00
*
* @ global object
2007-12-04 10:35:25 +00:00
* @ param int $groupid The id of the group of advcheckboxes this element controls
2009-05-25 08:27:25 +00:00
* @ param string $buttontext The text of the link . Defaults to " select all/none "
2007-12-04 10:35:25 +00:00
* @ param array $attributes associative array of HTML attributes
* @ param int $originalValue The original general state of the checkboxes before the user first clicks this element
*/
2008-07-31 22:15:30 +00:00
function add_checkbox_controller ( $groupid , $buttontext , $attributes , $originalValue = 0 ) {
2007-12-04 10:35:25 +00:00
global $CFG ;
if ( empty ( $text )) {
$text = get_string ( 'selectallornone' , 'form' );
}
$mform = $this -> _form ;
$select_value = optional_param ( 'checkbox_controller' . $groupid , null , PARAM_INT );
if ( $select_value == 0 || is_null ( $select_value )) {
$new_select_value = 1 ;
} else {
$new_select_value = 0 ;
}
$mform -> addElement ( 'hidden' , " checkbox_controller $groupid " );
2009-09-26 17:07:08 +00:00
$mform -> setType ( " checkbox_controller $groupid " , PARAM_INT );
2007-12-04 10:35:25 +00:00
$mform -> setConstants ( array ( " checkbox_controller $groupid " => $new_select_value ));
2008-07-31 22:15:30 +00:00
2007-12-04 10:35:25 +00:00
// Locate all checkboxes for this group and set their value, IF the optional param was given
if ( ! is_null ( $select_value )) {
foreach ( $this -> _form -> _elements as $element ) {
if ( $element -> getAttribute ( 'class' ) == " checkboxgroup $groupid " ) {
$mform -> setConstants ( array ( $element -> getAttribute ( 'name' ) => $select_value ));
}
}
}
$checkbox_controller_name = 'nosubmit_checkbox_controller' . $groupid ;
$mform -> registerNoSubmitButton ( $checkbox_controller_name );
2008-07-31 22:15:30 +00:00
2007-12-04 10:35:25 +00:00
// Prepare Javascript for submit element
$js = " \n //<![CDATA[ \n " ;
if ( ! defined ( 'HTML_QUICKFORM_CHECKBOXCONTROLLER_EXISTS' )) {
$js .= <<< EOS
function html_quickform_toggle_checkboxes ( group ) {
var checkboxes = getElementsByClassName ( document , 'input' , 'checkboxgroup' + group );
var newvalue = false ;
var global = eval ( 'html_quickform_checkboxgroup' + group + ';' );
if ( global == 1 ) {
2008-07-31 22:15:30 +00:00
eval ( 'html_quickform_checkboxgroup' + group + ' = 0;' );
2007-12-04 10:35:25 +00:00
newvalue = '' ;
} else {
2008-07-31 22:15:30 +00:00
eval ( 'html_quickform_checkboxgroup' + group + ' = 1;' );
2007-12-04 10:35:25 +00:00
newvalue = 'checked' ;
}
for ( i = 0 ; i < checkboxes . length ; i ++ ) {
2008-07-31 22:15:30 +00:00
checkboxes [ i ] . checked = newvalue ;
2007-12-04 10:35:25 +00:00
}
}
EOS ;
define ( 'HTML_QUICKFORM_CHECKBOXCONTROLLER_EXISTS' , true );
}
$js .= " \n var html_quickform_checkboxgroup $groupid = $originalValue ; \n " ;
2008-07-31 22:15:30 +00:00
2007-12-04 10:35:25 +00:00
$js .= " //]]> \n " ;
2008-07-31 22:15:30 +00:00
2007-12-04 10:35:25 +00:00
require_once ( " $CFG->libdir /form/submitlink.php " );
$submitlink = new MoodleQuickForm_submitlink ( $checkbox_controller_name , $attributes );
$submitlink -> _js = $js ;
$submitlink -> _onclick = " html_quickform_toggle_checkboxes( $groupid ); return false; " ;
2008-07-31 22:15:30 +00:00
$mform -> addElement ( $submitlink );
2007-12-04 10:35:25 +00:00
$mform -> setDefault ( $checkbox_controller_name , $text );
}
2006-12-19 07:03:08 +00:00
/**
2006-12-28 15:43:47 +00:00
* Use this method to a cancel and submit button to the end of your form . Pass a param of false
2006-12-19 07:03:08 +00:00
* if you don ' t want a cancel button in your form . If you have a cancel button make sure you
* check for it being pressed using is_cancelled () and redirecting if it is true before trying to
2007-01-12 18:52:09 +00:00
* get data with get_data () .
2006-12-19 07:03:08 +00:00
*
* @ param boolean $cancel whether to show cancel button , default true
* @ param string $submitlabel label for submit button , defaults to get_string ( 'savechanges' )
*/
2006-12-28 15:43:47 +00:00
function add_action_buttons ( $cancel = true , $submitlabel = null ){
2006-12-19 07:03:08 +00:00
if ( is_null ( $submitlabel )){
$submitlabel = get_string ( 'savechanges' );
}
$mform =& $this -> _form ;
2006-12-28 15:43:47 +00:00
if ( $cancel ){
//when two elements we need a group
2006-12-19 07:03:08 +00:00
$buttonarray = array ();
$buttonarray [] = & $mform -> createElement ( 'submit' , 'submitbutton' , $submitlabel );
2006-12-28 15:43:47 +00:00
$buttonarray [] = & $mform -> createElement ( 'cancel' );
2006-12-19 07:03:08 +00:00
$mform -> addGroup ( $buttonarray , 'buttonar' , '' , array ( ' ' ), false );
2007-08-03 13:08:05 +00:00
$mform -> closeHeaderBefore ( 'buttonar' );
2006-12-19 07:03:08 +00:00
} else {
//no group needed
$mform -> addElement ( 'submit' , 'submitbutton' , $submitlabel );
2007-08-03 13:08:05 +00:00
$mform -> closeHeaderBefore ( 'submitbutton' );
2006-12-19 07:03:08 +00:00
}
}
2010-05-18 07:58:45 +00:00
/**
2010-05-22 19:10:44 +00:00
* Adds an initialisation call for a standard JavaScript enhancement .
2010-05-18 07:58:45 +00:00
*
* This function is designed to add an initialisation call for a JavaScript
2010-05-22 19:10:44 +00:00
* enhancement that should exist within javascript - static M . form . init_ { enhancementname } .
2010-05-18 07:58:45 +00:00
*
* Current options :
* - Selectboxes
* - smartselect : Turns a nbsp indented select box into a custom drop down
* control that supports multilevel and category selection .
* $enhancement = 'smartselect' ;
* $options = array ( 'selectablecategories' => true | false )
*
* @ since 2.0
* @ param string | element $element
* @ param string $enhancement
* @ param array $options
* @ param array $strings
*/
function init_javascript_enhancement ( $element , $enhancement , array $options = array (), array $strings = null ) {
global $PAGE ;
if ( is_string ( $element )) {
$element = $this -> _form -> getElement ( $element );
}
if ( is_object ( $element )) {
$element -> _generateId ();
$elementid = $element -> getAttribute ( 'id' );
$PAGE -> requires -> js_init_call ( 'M.form.init_' . $enhancement , array ( $elementid , $options ));
if ( is_array ( $strings )) {
foreach ( $strings as $string ) {
if ( is_array ( $string )) {
call_user_method_array ( 'string_for_js' , $PAGE -> requires , $string );
} else {
$PAGE -> requires -> string_for_js ( $string , 'moodle' );
}
}
}
}
}
2006-10-12 07:33:57 +00:00
}
2006-11-12 07:28:13 +00:00
/**
* You never extend this class directly . The class methods of this class are available from
2007-12-04 10:35:25 +00:00
* the private $this -> _form property on moodleform and its children . You generally only
2006-11-12 07:28:13 +00:00
* call methods on this class from within abstract methods that you override on moodleform such
* as definition and definition_after_data
*
2009-05-25 08:27:25 +00:00
* @ package moodlecore
* @ copyright Jamie Pratt < me @ jamiep . org >
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
2006-11-12 07:28:13 +00:00
*/
2006-10-12 07:33:57 +00:00
class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
2009-05-25 08:27:25 +00:00
/** @var array */
2006-10-12 07:33:57 +00:00
var $_types = array ();
2006-11-21 09:17:46 +00:00
var $_dependencies = array ();
2006-12-04 09:36:30 +00:00
/**
* Array of buttons that if pressed do not result in the processing of the form .
*
* @ var array
*/
var $_noSubmitButtons = array ();
/**
* Array of buttons that if pressed do not result in the processing of the form .
*
* @ var array
*/
var $_cancelButtons = array ();
2006-10-12 07:33:57 +00:00
2006-12-14 12:44:10 +00:00
/**
* Array whose keys are element names . If the key exists this is a advanced element
*
* @ var array
*/
var $_advancedElements = array ();
/**
* Whether to display advanced elements ( on page load )
*
* @ var boolean
*/
var $_showAdvanced = null ;
2006-12-28 09:32:45 +00:00
/**
2010-05-22 19:10:44 +00:00
* The form name is derived from the class name of the wrapper minus the trailing form
2006-12-28 09:32:45 +00:00
* It is a name with words joined by underscores whereas the id attribute is words joined by
* underscores .
*
* @ var unknown_type
*/
var $_formName = '' ;
2007-07-06 04:03:51 +00:00
2007-08-03 13:08:05 +00:00
/**
* String with the html for hidden params passed in as part of a moodle_url object for the action . Output in the form .
*
* @ var string
*/
var $_pageparams = '' ;
2006-09-24 17:04:51 +00:00
/**
* Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless
2009-05-25 08:27:25 +00:00
*
* @ global object
* @ staticvar int $formcounter
2006-09-24 17:04:51 +00:00
* @ param string $formName Form ' s name .
* @ param string $method ( optional ) Form 's method defaults to ' POST '
2007-08-03 13:08:05 +00:00
* @ param mixed $action ( optional ) Form ' s action - string or moodle_url
2006-09-24 17:04:51 +00:00
* @ param string $target ( optional ) Form ' s target defaults to none
* @ param mixed $attributes ( optional ) Extra attributes for < form > tag
* @ access public
*/
2006-10-12 07:33:57 +00:00
function MoodleQuickForm ( $formName , $method , $action , $target = '' , $attributes = null ){
2009-07-01 04:11:52 +00:00
global $CFG , $OUTPUT ;
2007-01-27 19:56:08 +00:00
2007-01-07 12:46:47 +00:00
static $formcounter = 1 ;
2006-10-12 07:33:57 +00:00
2006-09-24 17:04:51 +00:00
HTML_Common :: HTML_Common ( $attributes );
$target = empty ( $target ) ? array () : array ( 'target' => $target );
2006-12-28 09:32:45 +00:00
$this -> _formName = $formName ;
2007-08-03 13:08:05 +00:00
if ( is_a ( $action , 'moodle_url' )){
2010-01-17 09:06:55 +00:00
$this -> _pageparams = html_writer :: input_hidden_params ( $action );
2010-01-17 09:37:30 +00:00
$action = $action -> out_omit_querystring ();
2007-08-03 13:08:05 +00:00
} else {
$this -> _pageparams = '' ;
}
2006-09-24 17:04:51 +00:00
//no 'name' atttribute for form in xhtml strict :
2008-11-27 02:49:02 +00:00
$attributes = array ( 'action' => $action , 'method' => $method ,
'accept-charset' => 'utf-8' , 'id' => 'mform' . $formcounter ) + $target ;
2007-01-07 12:46:47 +00:00
$formcounter ++ ;
2006-09-24 17:04:51 +00:00
$this -> updateAttributes ( $attributes );
2006-10-12 07:33:57 +00:00
//this is custom stuff for Moodle :
2006-09-24 17:04:51 +00:00
$oldclass = $this -> getAttribute ( 'class' );
if ( ! empty ( $oldclass )){
$this -> updateAttributes ( array ( 'class' => $oldclass . ' mform' ));
} else {
2006-09-26 09:42:42 +00:00
$this -> updateAttributes ( array ( 'class' => 'mform' ));
2006-09-24 17:04:51 +00:00
}
2009-12-16 21:50:45 +00:00
$this -> _reqHTML = '<img class="req" title="' . get_string ( 'requiredelement' , 'form' ) . '" alt="' . get_string ( 'requiredelement' , 'form' ) . '" src="' . $OUTPUT -> pix_url ( 'req' ) . '" />' ;
$this -> _advancedHTML = '<img class="adv" title="' . get_string ( 'advancedelement' , 'form' ) . '" alt="' . get_string ( 'advancedelement' , 'form' ) . '" src="' . $OUTPUT -> pix_url ( 'adv' ) . '" />' ;
$this -> setRequiredNote ( get_string ( 'somefieldsrequired' , 'form' , '<img alt="' . get_string ( 'requiredelement' , 'form' ) . '" src="' . $OUTPUT -> pix_url ( 'req' ) . '" />' ));
2006-12-14 12:44:10 +00:00
}
2006-12-19 07:03:08 +00:00
/**
* Use this method to indicate an element in a form is an advanced field . If items in a form
* are marked as advanced then 'Hide/Show Advanced' buttons will automatically be displayed in the
* form so the user can decide whether to display advanced form controls .
*
* If you set a header element to advanced then all elements it contains will also be set as advanced .
*
* @ param string $elementName group or element name ( not the element name of something inside a group ) .
* @ param boolean $advanced default true sets the element to advanced . False removes advanced mark .
*/
function setAdvanced ( $elementName , $advanced = true ){
if ( $advanced ){
$this -> _advancedElements [ $elementName ] = '' ;
} elseif ( isset ( $this -> _advancedElements [ $elementName ])) {
unset ( $this -> _advancedElements [ $elementName ]);
}
if ( $advanced && $this -> getElementType ( 'mform_showadvanced_last' ) === false ){
$this -> setShowAdvanced ();
$this -> registerNoSubmitButton ( 'mform_showadvanced' );
$this -> addElement ( 'hidden' , 'mform_showadvanced_last' );
2009-09-26 17:07:08 +00:00
$this -> setType ( 'mform_showadvanced_last' , PARAM_INT );
2006-12-19 07:03:08 +00:00
}
}
/**
* Set whether to show advanced elements in the form on first displaying form . Default is not to
* display advanced elements in the form until 'Show Advanced' is pressed .
*
* You can get the last state of the form and possibly save it for this user by using
* value 'mform_showadvanced_last' in submitted data .
*
* @ param boolean $showadvancedNow
*/
function setShowAdvanced ( $showadvancedNow = null ){
if ( $showadvancedNow === null ){
if ( $this -> _showAdvanced !== null ){
return ;
} else { //if setShowAdvanced is called without any preference
//make the default to not show advanced elements.
2006-12-28 09:32:45 +00:00
$showadvancedNow = get_user_preferences (
moodle_strtolower ( $this -> _formName . '_showadvanced' , 0 ));
2006-12-19 07:03:08 +00:00
}
}
//value of hidden element
$hiddenLast = optional_param ( 'mform_showadvanced_last' , - 1 , PARAM_INT );
//value of button
$buttonPressed = optional_param ( 'mform_showadvanced' , 0 , PARAM_RAW );
//toggle if button pressed or else stay the same
if ( $hiddenLast == - 1 ) {
$next = $showadvancedNow ;
} elseif ( $buttonPressed ) { //toggle on button press
$next = ! $hiddenLast ;
} else {
$next = $hiddenLast ;
}
$this -> _showAdvanced = $next ;
2006-12-28 09:32:45 +00:00
if ( $showadvancedNow != $next ){
set_user_preference ( $this -> _formName . '_showadvanced' , $next );
}
2006-12-19 07:03:08 +00:00
$this -> setConstants ( array ( 'mform_showadvanced_last' => $next ));
2006-12-14 12:44:10 +00:00
}
function getShowAdvanced (){
return $this -> _showAdvanced ;
}
/**
* Accepts a renderer
*
2009-05-25 08:27:25 +00:00
* @ param object $renderer HTML_QuickForm_Renderer An HTML_QuickForm_Renderer object
2006-12-14 12:44:10 +00:00
* @ access public
* @ return void
*/
2007-11-12 17:12:35 +00:00
function accept ( & $renderer ) {
2006-12-14 12:44:10 +00:00
if ( method_exists ( $renderer , 'setAdvancedElements' )){
//check for visible fieldsets where all elements are advanced
//and mark these headers as advanced as well.
//And mark all elements in a advanced header as advanced
$stopFields = $renderer -> getStopFieldSetElements ();
$lastHeader = null ;
$lastHeaderAdvanced = false ;
$anyAdvanced = false ;
foreach ( array_keys ( $this -> _elements ) as $elementIndex ){
$element =& $this -> _elements [ $elementIndex ];
2007-11-12 17:12:35 +00:00
// if closing header and any contained element was advanced then mark it as advanced
2006-12-14 12:44:10 +00:00
if ( $element -> getType () == 'header' || in_array ( $element -> getName (), $stopFields )){
2007-11-12 17:12:35 +00:00
if ( $anyAdvanced && ! is_null ( $lastHeader )){
2006-12-14 12:44:10 +00:00
$this -> setAdvanced ( $lastHeader -> getName ());
}
$lastHeaderAdvanced = false ;
2007-11-12 17:12:35 +00:00
unset ( $lastHeader );
$lastHeader = null ;
2006-12-14 12:44:10 +00:00
} elseif ( $lastHeaderAdvanced ) {
$this -> setAdvanced ( $element -> getName ());
}
2007-11-12 17:12:35 +00:00
2006-12-14 12:44:10 +00:00
if ( $element -> getType () == 'header' ){
$lastHeader =& $element ;
$anyAdvanced = false ;
$lastHeaderAdvanced = isset ( $this -> _advancedElements [ $element -> getName ()]);
} elseif ( isset ( $this -> _advancedElements [ $element -> getName ()])){
$anyAdvanced = true ;
}
}
2007-11-12 17:12:35 +00:00
// the last header may not be closed yet...
if ( $anyAdvanced && ! is_null ( $lastHeader )){
$this -> setAdvanced ( $lastHeader -> getName ());
}
2006-12-14 12:44:10 +00:00
$renderer -> setAdvancedElements ( $this -> _advancedElements );
}
parent :: accept ( $renderer );
}
2009-05-25 08:27:25 +00:00
/**
* @ param string $elementName
*/
2006-12-14 12:44:10 +00:00
function closeHeaderBefore ( $elementName ){
$renderer =& $this -> defaultRenderer ();
$renderer -> addStopFieldsetElements ( $elementName );
2006-09-24 17:04:51 +00:00
}
2006-11-08 06:22:58 +00:00
2006-11-12 07:28:13 +00:00
/**
* Should be used for all elements of a form except for select , radio and checkboxes which
* clean their own data .
*
* @ param string $elementname
* @ param integer $paramtype use the constants PARAM_ *.
* * PARAM_CLEAN is deprecated and you should try to use a more specific type .
* * PARAM_TEXT should be used for cleaning data that is expected to be plain text .
* It will strip all html tags . But will still let tags for multilang support
* through .
* * PARAM_RAW means no cleaning whatsoever , it is used mostly for data from the
* html editor . Data from the editor is later cleaned before display using
* format_text () function . PARAM_RAW can also be used for data that is validated
* by some other way or printed by p () or s () .
* * PARAM_INT should be used for integers .
* * PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying
* form actions .
*/
2006-10-12 07:33:57 +00:00
function setType ( $elementname , $paramtype ) {
$this -> _types [ $elementname ] = $paramtype ;
}
2006-11-09 08:38:40 +00:00
2006-11-12 07:28:13 +00:00
/**
* See description of setType above . This can be used to set several types at once .
*
* @ param array $paramtypes
*/
2006-10-12 14:15:59 +00:00
function setTypes ( $paramtypes ) {
$this -> _types = $paramtypes + $this -> _types ;
}
2006-11-09 08:38:40 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ param array $submission
* @ param array $files
*/
2006-11-09 08:38:40 +00:00
function updateSubmission ( $submission , $files ) {
$this -> _flagSubmitted = false ;
2006-10-12 07:33:57 +00:00
if ( empty ( $submission )) {
$this -> _submitValues = array ();
} else {
foreach ( $submission as $key => $s ) {
if ( array_key_exists ( $key , $this -> _types )) {
$submission [ $key ] = clean_param ( $s , $this -> _types [ $key ]);
}
}
2008-06-09 16:53:30 +00:00
$this -> _submitValues = $submission ;
2006-10-12 07:33:57 +00:00
$this -> _flagSubmitted = true ;
}
2006-11-09 08:38:40 +00:00
if ( empty ( $files )) {
$this -> _submitFiles = array ();
} else {
$this -> _submitFiles = $files ;
$this -> _flagSubmitted = true ;
}
2006-10-24 11:05:50 +00:00
// need to tell all elements that they need to update their value attribute.
foreach ( array_keys ( $this -> _elements ) as $key ) {
$this -> _elements [ $key ] -> onQuickFormEvent ( 'updateValue' , null , $this );
}
2006-10-12 07:33:57 +00:00
}
2009-05-25 08:27:25 +00:00
/**
* @ return string
*/
2006-09-24 17:04:51 +00:00
function getReqHTML (){
return $this -> _reqHTML ;
}
2009-11-01 11:31:16 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ return string
*/
2006-12-14 12:44:10 +00:00
function getAdvancedHTML (){
return $this -> _advancedHTML ;
}
2006-10-12 07:33:57 +00:00
/**
2006-11-12 07:28:13 +00:00
* Initializes a default form value . Used to specify the default for a new entry where
2007-01-12 18:52:09 +00:00
* no data is loaded in using moodleform :: set_data ()
2006-10-12 07:33:57 +00:00
*
2008-06-09 16:53:30 +00:00
* note : $slashed param removed
*
2006-10-12 07:33:57 +00:00
* @ param string $elementname element name
* @ param mixed $values values for that element name
* @ access public
* @ return void
*/
2008-06-09 16:53:30 +00:00
function setDefault ( $elementName , $defaultValue ){
$this -> setDefaults ( array ( $elementName => $defaultValue ));
2006-10-12 07:33:57 +00:00
} // end func setDefault
2006-09-24 17:04:51 +00:00
/**
2006-10-12 14:15:59 +00:00
* Add an array of buttons to the form
2006-10-12 07:33:57 +00:00
* @ param array $buttons An associative array representing help button to attach to
2006-09-24 17:04:51 +00:00
* to the form . keys of array correspond to names of elements in form .
2010-07-28 11:04:35 +00:00
* @ deprecated since Moodle 2.0 - use addHelpButton () call on each element manually
2009-05-25 08:27:25 +00:00
* @ param bool $suppresscheck
* @ param string $function
2006-09-24 17:04:51 +00:00
* @ access public
*/
2006-11-13 07:43:22 +00:00
function setHelpButtons ( $buttons , $suppresscheck = false , $function = 'helpbutton' ){
2006-10-12 07:33:57 +00:00
2010-07-28 11:04:35 +00:00
debugging ( 'function moodle_form::setHelpButtons() is deprecated' );
//foreach ($buttons as $elementname => $button){
// $this->setHelpButton($elementname, $button, $suppresscheck, $function);
//}
2006-09-24 17:04:51 +00:00
}
2006-10-12 14:15:59 +00:00
/**
2006-11-12 07:28:13 +00:00
* Add a single button .
2006-10-12 14:15:59 +00:00
*
2010-04-30 09:57:32 +00:00
* @ deprecated use addHelpButton () instead
2006-10-12 14:15:59 +00:00
* @ param string $elementname name of the element to add the item to
2009-05-25 08:27:25 +00:00
* @ param array $button arguments to pass to function $function
* @ param boolean $suppresscheck whether to throw an error if the element
2006-10-12 14:15:59 +00:00
* doesn ' t exist .
2006-11-13 07:43:22 +00:00
* @ param string $function - function to generate html from the arguments in $button
2009-05-25 08:27:25 +00:00
* @ param string $function
2006-10-12 14:15:59 +00:00
*/
2009-12-30 15:19:55 +00:00
function setHelpButton ( $elementname , $buttonargs , $suppresscheck = false , $function = 'helpbutton' ){
2009-08-20 08:50:50 +00:00
global $OUTPUT ;
2010-04-11 14:57:59 +00:00
//TODO: obsolete this function completely
2009-12-30 15:19:55 +00:00
if ( $function !== 'helpbutton' ) {
2010-04-11 14:57:59 +00:00
//debugging('parameter $function in moodle_form::setHelpButton() is not supported any more');
2009-12-30 15:19:55 +00:00
}
$buttonargs = ( array ) $buttonargs ;
if ( array_key_exists ( $elementname , $this -> _elementIndex )) {
2006-10-12 14:15:59 +00:00
//_elements has a numeric index, this code accesses the elements by name
2009-12-30 15:19:55 +00:00
$element = $this -> _elements [ $this -> _elementIndex [ $elementname ]];
2009-08-20 08:50:50 +00:00
2009-12-30 15:19:55 +00:00
$page = isset ( $buttonargs [ 0 ]) ? $buttonargs [ 0 ] : null ;
$text = isset ( $buttonargs [ 1 ]) ? $buttonargs [ 1 ] : null ;
$module = isset ( $buttonargs [ 2 ]) ? $buttonargs [ 2 ] : 'moodle' ;
$linktext = isset ( $buttonargs [ 3 ]) ? $buttonargs [ 3 ] : false ;
2010-04-13 20:34:27 +00:00
$element -> _helpbutton = $OUTPUT -> old_help_icon ( $page , $text , $module , $linktext );
2009-08-20 08:50:50 +00:00
2009-12-30 15:19:55 +00:00
} else if ( ! $suppresscheck ) {
2006-10-12 14:15:59 +00:00
print_error ( 'nonexistentformelements' , 'form' , '' , $elementname );
2006-10-24 11:05:50 +00:00
}
2006-10-12 14:15:59 +00:00
}
2006-10-12 07:33:57 +00:00
2010-04-10 09:10:08 +00:00
/**
2010-04-13 21:51:49 +00:00
* Add a help button to element , only one button per element is allowed .
*
2010-04-30 09:57:32 +00:00
* This is new , simplified and preferable method of setting a help icon on form elements .
* It uses the new $OUTPUT -> help_icon () .
*
* Typically , you will provide the same identifier and the component as you have used for the
* label of the element . The string identifier with the _help suffix added is then used
* as the help string .
*
2010-04-13 21:51:49 +00:00
* There has to be two strings defined :
* 1 / get_string ( $identifier , $component ) - the title of the help page
2010-04-23 07:46:35 +00:00
* 2 / get_string ( $identifier . '_help' , $component ) - the actual help page text
2010-04-10 09:10:08 +00:00
*
2010-04-30 09:57:32 +00:00
* @ since 2.0
2010-04-10 09:10:08 +00:00
* @ param string $elementname name of the element to add the item to
2010-05-22 19:10:44 +00:00
* @ param string $identifier help string identifier without _help suffix
2010-04-30 09:57:32 +00:00
* @ param string $component component name to look the help string in
* @ param string $linktext optional text to display next to the icon
* @ param boolean $suppresscheck set to true if the element may not exist
2010-04-10 09:10:08 +00:00
* @ return void
*/
2010-04-13 21:51:49 +00:00
function addHelpButton ( $elementname , $identifier , $component = 'moodle' , $linktext = '' , $suppresscheck = false ) {
global $OUTPUT ;
2010-04-10 09:10:08 +00:00
if ( array_key_exists ( $elementname , $this -> _elementIndex )) {
2010-05-20 06:26:40 +00:00
$element = $this -> _elements [ $this -> _elementIndex [ $elementname ]];
$element -> _helpbutton = $OUTPUT -> help_icon ( $identifier , $component , $linktext );
2010-04-10 09:10:08 +00:00
} else if ( ! $suppresscheck ) {
debugging ( get_string ( 'nonexistentformelements' , 'form' , $elementname ));
}
}
2008-10-13 19:39:27 +00:00
/**
2010-05-22 19:10:44 +00:00
* Set constant value not overridden by _POST or _GET
2008-10-13 19:39:27 +00:00
* note : this does not work for complex names with [] :- (
2009-05-25 08:27:25 +00:00
*
2008-10-13 19:39:27 +00:00
* @ param string $elname name of element
* @ param mixed $value
* @ return void
*/
function setConstant ( $elname , $value ) {
$this -> _constantValues = HTML_QuickForm :: arrayMerge ( $this -> _constantValues , array ( $elname => $value ));
$element =& $this -> getElement ( $elname );
$element -> onQuickFormEvent ( 'updateValue' , null , $this );
}
2009-05-25 08:27:25 +00:00
/**
* @ param string $elementList
*/
2008-06-09 16:53:30 +00:00
function exportValues ( $elementList = null ){
2007-01-12 04:36:02 +00:00
$unfiltered = array ();
if ( null === $elementList ) {
// iterate over all elements, calling their exportValue() methods
2007-01-12 08:36:24 +00:00
$emptyarray = array ();
2007-01-12 04:36:02 +00:00
foreach ( array_keys ( $this -> _elements ) as $key ) {
if ( $this -> _elements [ $key ] -> isFrozen () && ! $this -> _elements [ $key ] -> _persistantFreeze ){
2007-01-12 08:36:24 +00:00
$value = $this -> _elements [ $key ] -> exportValue ( $emptyarray , true );
2007-01-12 04:36:02 +00:00
} else {
$value = $this -> _elements [ $key ] -> exportValue ( $this -> _submitValues , true );
}
if ( is_array ( $value )) {
// This shit throws a bogus warning in PHP 4.3.x
$unfiltered = HTML_QuickForm :: arrayMerge ( $unfiltered , $value );
}
}
} else {
if ( ! is_array ( $elementList )) {
$elementList = array_map ( 'trim' , explode ( ',' , $elementList ));
}
foreach ( $elementList as $elementName ) {
$value = $this -> exportValue ( $elementName );
if ( PEAR :: isError ( $value )) {
return $value ;
}
2008-09-07 13:30:46 +00:00
//oh, stock QuickFOrm was returning array of arrays!
$unfiltered = HTML_QuickForm :: arrayMerge ( $unfiltered , $value );
2007-01-12 04:36:02 +00:00
}
}
2006-10-12 07:33:57 +00:00
2008-06-09 16:53:30 +00:00
return $unfiltered ;
2006-09-24 17:04:51 +00:00
}
2006-12-28 09:32:45 +00:00
/**
* Adds a validation rule for the given field
*
* If the element is in fact a group , it will be considered as a whole .
* To validate grouped elements as separated entities ,
* use addGroupRule instead of addRule .
*
* @ param string $element Form element name
* @ param string $message Message to display for invalid data
* @ param string $type Rule type , use getRegisteredRules () to get types
* @ param string $format ( optional ) Required for extra rule data
* @ param string $validation ( optional ) Where to perform validation : " server " , " client "
* @ param boolean $reset Client - side validation : reset the form element to its original value if there is an error ?
* @ param boolean $force Force the rule to be applied , even if the target form element does not exist
* @ access public
*/
function addRule ( $element , $message , $type , $format = null , $validation = 'server' , $reset = false , $force = false )
{
parent :: addRule ( $element , $message , $type , $format , $validation , $reset , $force );
if ( $validation == 'client' ) {
$this -> updateAttributes ( array ( 'onsubmit' => 'try { var myValidator = validate_' . $this -> _formName . '; } catch(e) { return true; } return myValidator(this);' ));
}
} // end func addRule
/**
* Adds a validation rule for the given group of elements
*
* Only groups with a name can be assigned a validation rule
* Use addGroupRule when you need to validate elements inside the group .
* Use addRule if you need to validate the group as a whole . In this case ,
* the same rule will be applied to all elements in the group .
* Use addRule if you need to validate the group against a function .
*
* @ param string $group Form group name
* @ param mixed $arg1 Array for multiple elements or error message string for one element
* @ param string $type ( optional ) Rule type use getRegisteredRules () to get types
* @ param string $format ( optional ) Required for extra rule data
* @ param int $howmany ( optional ) How many valid elements should be in the group
* @ param string $validation ( optional ) Where to perform validation : " server " , " client "
* @ param bool $reset Client - side : whether to reset the element ' s value to its original state if validation failed .
* @ access public
*/
function addGroupRule ( $group , $arg1 , $type = '' , $format = null , $howmany = 0 , $validation = 'server' , $reset = false )
{
parent :: addGroupRule ( $group , $arg1 , $type , $format , $howmany , $validation , $reset );
if ( is_array ( $arg1 )) {
2007-01-21 10:32:42 +00:00
foreach ( $arg1 as $rules ) {
2006-12-28 09:32:45 +00:00
foreach ( $rules as $rule ) {
$validation = ( isset ( $rule [ 3 ]) && 'client' == $rule [ 3 ]) ? 'client' : 'server' ;
if ( 'client' == $validation ) {
$this -> updateAttributes ( array ( 'onsubmit' => 'try { var myValidator = validate_' . $this -> _formName . '; } catch(e) { return true; } return myValidator(this);' ));
}
}
}
} elseif ( is_string ( $arg1 )) {
if ( $validation == 'client' ) {
2007-01-21 10:32:42 +00:00
$this -> updateAttributes ( array ( 'onsubmit' => 'try { var myValidator = validate_' . $this -> _formName . '; } catch(e) { return true; } return myValidator(this);' ));
2006-12-28 09:32:45 +00:00
}
}
} // end func addGroupRule
// }}}
2006-10-14 12:32:31 +00:00
/**
* Returns the client side validation script
*
* The code here was copied from HTML_QuickForm_DHTMLRulesTableless who copied it from HTML_QuickForm
* and slightly modified to run rules per - element
* Needed to override this because of an error with client side validation of grouped elements .
*
* @ access public
* @ return string Javascript to perform validation , empty string if no 'client' rules were added
*/
function getValidationScript ()
{
if ( empty ( $this -> _rules ) || empty ( $this -> _attributes [ 'onsubmit' ])) {
return '' ;
}
include_once ( 'HTML/QuickForm/RuleRegistry.php' );
$registry =& HTML_QuickForm_RuleRegistry :: singleton ();
$test = array ();
$js_escape = array (
" \r " => '\r' ,
" \n " => '\n' ,
" \t " => '\t' ,
" ' " => " \\ ' " ,
'"' => '\"' ,
'\\' => '\\\\'
);
foreach ( $this -> _rules as $elementName => $rules ) {
foreach ( $rules as $rule ) {
if ( 'client' == $rule [ 'validation' ]) {
2006-11-12 07:28:13 +00:00
unset ( $element ); //TODO: find out how to properly initialize it
2006-10-14 12:32:31 +00:00
$dependent = isset ( $rule [ 'dependent' ]) && is_array ( $rule [ 'dependent' ]);
$rule [ 'message' ] = strtr ( $rule [ 'message' ], $js_escape );
if ( isset ( $rule [ 'group' ])) {
$group =& $this -> getElement ( $rule [ 'group' ]);
// No JavaScript validation for frozen elements
if ( $group -> isFrozen ()) {
continue 2 ;
}
$elements =& $group -> getElements ();
foreach ( array_keys ( $elements ) as $key ) {
if ( $elementName == $group -> getElementName ( $key )) {
$element =& $elements [ $key ];
break ;
}
}
} elseif ( $dependent ) {
$element = array ();
$element [] =& $this -> getElement ( $elementName );
2007-01-21 10:32:42 +00:00
foreach ( $rule [ 'dependent' ] as $elName ) {
2006-10-14 12:32:31 +00:00
$element [] =& $this -> getElement ( $elName );
}
} else {
$element =& $this -> getElement ( $elementName );
}
// No JavaScript validation for frozen elements
if ( is_object ( $element ) && $element -> isFrozen ()) {
continue 2 ;
} elseif ( is_array ( $element )) {
foreach ( array_keys ( $element ) as $key ) {
if ( $element [ $key ] -> isFrozen ()) {
continue 3 ;
}
}
}
// Fix for bug displaying errors for elements in a group
//$test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule);
$test [ $elementName ][ 0 ][] = $registry -> getValidationScript ( $element , $elementName , $rule );
$test [ $elementName ][ 1 ] = $element ;
//end of fix
}
}
}
2007-04-23 16:19:25 +00:00
// Fix for MDL-9524. If you don't do this, then $element may be left as a reference to one of the fields in
// the form, and then that form field gets corrupted by the code that follows.
unset ( $element );
2006-10-14 12:32:31 +00:00
$js = '
< script type = " text/javascript " >
//<![CDATA[
2006-12-04 22:00:47 +00:00
var skipClientValidation = false ;
2006-10-14 12:32:31 +00:00
function qf_errorHandler ( element , _qfMsg ) {
div = element . parentNode ;
if ( _qfMsg != \ ' \ ' ) {
2006-12-05 21:43:33 +00:00
var errorSpan = document . getElementById ( \ ' id_error_\ ' + element . name );
2006-12-05 14:27:24 +00:00
if ( ! errorSpan ) {
errorSpan = document . createElement ( " span " );
2006-12-05 21:43:33 +00:00
errorSpan . id = \ ' id_error_\ ' + element . name ;
errorSpan . className = " error " ;
2006-12-05 21:48:44 +00:00
element . parentNode . insertBefore ( errorSpan , element . parentNode . firstChild );
2006-10-14 12:32:31 +00:00
}
2006-12-05 21:48:44 +00:00
2006-12-05 14:27:24 +00:00
while ( errorSpan . firstChild ) {
errorSpan . removeChild ( errorSpan . firstChild );
2006-10-14 12:32:31 +00:00
}
2006-10-24 11:05:50 +00:00
2006-12-05 14:27:24 +00:00
errorSpan . appendChild ( document . createTextNode ( _qfMsg . substring ( 3 )));
2006-12-05 21:43:33 +00:00
errorSpan . appendChild ( document . createElement ( " br " ));
2006-10-14 12:32:31 +00:00
if ( div . className . substr ( div . className . length - 6 , 6 ) != " error "
&& div . className != " error " ) {
div . className += " error " ;
}
return false ;
} else {
2006-12-05 21:43:33 +00:00
var errorSpan = document . getElementById ( \ ' id_error_\ ' + element . name );
2006-12-05 14:27:24 +00:00
if ( errorSpan ) {
errorSpan . parentNode . removeChild ( errorSpan );
2006-10-14 12:32:31 +00:00
}
if ( div . className . substr ( div . className . length - 6 , 6 ) == " error " ) {
div . className = div . className . substr ( 0 , div . className . length - 6 );
} else if ( div . className == " error " ) {
div . className = " " ;
}
return true ;
}
} ' ;
$validateJS = '' ;
foreach ( $test as $elementName => $jsandelement ) {
// Fix for bug displaying errors for elements in a group
//unset($element);
list ( $jsArr , $element ) = $jsandelement ;
//end of fix
$js .= '
2006-12-28 09:32:45 +00:00
function validate_ ' . $this->_formName . ' _ ' . $elementName . ' ( element ) {
2006-10-14 12:32:31 +00:00
var value = \ ' \ ' ;
var errFlag = new Array ();
var _qfGroups = {};
var _qfMsg = \ ' \ ' ;
var frm = element . parentNode ;
2008-08-28 07:52:09 +00:00
while ( frm && frm . nodeName . toUpperCase () != " FORM " ) {
2006-10-14 12:32:31 +00:00
frm = frm . parentNode ;
}
' . join("\n", $jsArr) . '
return qf_errorHandler ( element , _qfMsg );
}
' ;
$validateJS .= '
2010-05-20 06:35:41 +00:00
ret = validate_ ' . $this->_formName . ' _ ' . $elementName.' ( frm . elements [ \ '' . $elementName . ' \ ' ]) && ret ;
2007-03-12 06:43:24 +00:00
if ( ! ret && ! first_focus ) {
first_focus = true ;
frm . elements [ \ '' . $elementName . ' \ ' ] . focus ();
}
' ;
2007-08-03 13:08:05 +00:00
2006-10-14 12:32:31 +00:00
// Fix for bug displaying errors for elements in a group
//unset($element);
//$element =& $this->getElement($elementName);
//end of fix
2006-12-28 09:32:45 +00:00
$valFunc = 'validate_' . $this -> _formName . '_' . $elementName . '(this)' ;
2006-10-14 12:32:31 +00:00
$onBlur = $element -> getAttribute ( 'onBlur' );
$onChange = $element -> getAttribute ( 'onChange' );
$element -> updateAttributes ( array ( 'onBlur' => $onBlur . $valFunc ,
'onChange' => $onChange . $valFunc ));
}
2006-12-05 14:27:24 +00:00
// do not rely on frm function parameter, because htmlarea breaks it when overloading the onsubmit method
2006-10-14 12:32:31 +00:00
$js .= '
2006-12-28 09:32:45 +00:00
function validate_ ' . $this->_formName . ' ( frm ) {
2006-12-04 22:00:47 +00:00
if ( skipClientValidation ) {
return true ;
}
2006-10-14 12:32:31 +00:00
var ret = true ;
2007-08-03 13:08:05 +00:00
2006-12-05 13:21:40 +00:00
var frm = document . getElementById ( \ '' . $this -> _attributes [ 'id' ] . ' \ ' )
2007-03-12 06:43:24 +00:00
var first_focus = false ;
2006-10-14 12:32:31 +00:00
' . $validateJS . ' ;
return ret ;
}
//]]>
</ script > ' ;
return $js ;
} // end func getValidationScript
function _setDefaultRuleMessages (){
foreach ( $this -> _rules as $field => $rulesarr ){
foreach ( $rulesarr as $key => $rule ){
if ( $rule [ 'message' ] === null ){
$a = new object ();
$a -> format = $rule [ 'format' ];
$str = get_string ( 'err_' . $rule [ 'type' ], 'form' , $a );
if ( strpos ( $str , '[[' ) !== 0 ){
$this -> _rules [ $field ][ $key ][ 'message' ] = $str ;
2006-10-24 11:05:50 +00:00
}
2006-10-14 12:32:31 +00:00
}
}
}
}
2006-11-08 06:22:58 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ return string
*/
2006-11-22 08:53:35 +00:00
function getLockOptionEndScript (){
2007-01-12 09:38:02 +00:00
$iname = $this -> getAttribute ( 'id' ) . 'items' ;
2007-01-03 14:44:17 +00:00
$js = '<script type="text/javascript">' . " \n " ;
2006-12-22 04:52:13 +00:00
$js .= '//<![CDATA[' . " \n " ;
2007-01-12 09:38:02 +00:00
$js .= " var $iname = Array(); \n " ;
foreach ( $this -> _dependencies as $dependentOn => $conditions ){
$js .= " { $iname } [' $dependentOn '] = Array(); \n " ;
foreach ( $conditions as $condition => $values ) {
$js .= " { $iname } [' $dependentOn '][' $condition '] = Array(); \n " ;
foreach ( $values as $value => $dependents ) {
$js .= " { $iname } [' $dependentOn '][' $condition '][' $value '] = Array(); \n " ;
$i = 0 ;
foreach ( $dependents as $dependent ) {
$elements = $this -> _getElNamesRecursive ( $dependent );
2007-11-12 17:12:35 +00:00
if ( empty ( $elements )) {
// probably element inside of some group
$elements = array ( $dependent );
}
2007-01-12 09:38:02 +00:00
foreach ( $elements as $element ) {
if ( $element == $dependentOn ) {
continue ;
}
$js .= " { $iname } [' $dependentOn '][' $condition '][' $value '][ $i ]=' $element '; \n " ;
$i ++ ;
}
2006-12-09 11:42:57 +00:00
}
}
2006-11-21 09:17:46 +00:00
}
2007-01-12 09:38:02 +00:00
}
2006-11-22 08:53:35 +00:00
$js .= " lockoptionsallsetup(' " . $this -> getAttribute ( 'id' ) . " '); \n " ;
2006-12-22 04:52:13 +00:00
$js .= '//]]>' . " \n " ;
2006-11-21 09:17:46 +00:00
$js .= '</script>' . " \n " ;
return $js ;
2006-11-08 06:22:58 +00:00
}
2006-11-22 08:53:35 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ param mixed $element
* @ return array
*/
2007-11-12 17:12:35 +00:00
function _getElNamesRecursive ( $element ) {
if ( is_string ( $element )) {
2007-08-03 13:08:05 +00:00
if ( ! $this -> elementExists ( $element )) {
return array ();
}
2007-11-12 17:12:35 +00:00
$element = $this -> getElement ( $element );
2006-11-22 08:53:35 +00:00
}
2007-11-12 17:12:35 +00:00
if ( is_a ( $element , 'HTML_QuickForm_group' )) {
$elsInGroup = $element -> getElements ();
2006-11-22 15:58:07 +00:00
$elNames = array ();
2006-11-22 08:53:35 +00:00
foreach ( $elsInGroup as $elInGroup ){
2007-11-24 13:37:07 +00:00
if ( is_a ( $elInGroup , 'HTML_QuickForm_group' )) {
// not sure if this would work - groups nested in groups
$elNames = array_merge ( $elNames , $this -> _getElNamesRecursive ( $elInGroup ));
} else {
$elNames [] = $element -> getElementName ( $elInGroup -> getName ());
}
2006-11-22 08:53:35 +00:00
}
2007-11-12 17:12:35 +00:00
} else if ( is_a ( $element , 'HTML_QuickForm_header' )) {
return array ();
} else if ( is_a ( $element , 'HTML_QuickForm_hidden' )) {
return array ();
} else if ( method_exists ( $element , 'getPrivateName' )) {
return array ( $element -> getPrivateName ());
} else {
$elNames = array ( $element -> getName ());
2006-11-22 08:53:35 +00:00
}
2007-11-12 17:12:35 +00:00
return $elNames ;
2006-11-21 09:17:46 +00:00
}
2007-11-12 17:12:35 +00:00
2006-11-21 09:33:48 +00:00
/**
* Adds a dependency for $elementName which will be disabled if $condition is met .
2006-11-22 15:58:07 +00:00
* If $condition = 'notchecked' ( default ) then the condition is that the $dependentOn element
* is not checked . If $condition = 'checked' then the condition is that the $dependentOn element
2007-09-25 14:40:49 +00:00
* is checked . If $condition is something else ( like " eq " for equals ) then it is checked to see if the value
* of the $dependentOn element is $condition ( such as equal ) to $value .
2006-11-21 09:33:48 +00:00
*
* @ param string $elementName the name of the element which will be disabled
* @ param string $dependentOn the name of the element whose state will be checked for
* condition
* @ param string $condition the condition to check
2006-12-04 09:36:30 +00:00
* @ param mixed $value used in conjunction with condition .
2006-11-21 09:33:48 +00:00
*/
2007-01-12 09:38:02 +00:00
function disabledIf ( $elementName , $dependentOn , $condition = 'notchecked' , $value = '1' ){
if ( ! array_key_exists ( $dependentOn , $this -> _dependencies )) {
$this -> _dependencies [ $dependentOn ] = array ();
}
if ( ! array_key_exists ( $condition , $this -> _dependencies [ $dependentOn ])) {
$this -> _dependencies [ $dependentOn ][ $condition ] = array ();
}
if ( ! array_key_exists ( $value , $this -> _dependencies [ $dependentOn ][ $condition ])) {
$this -> _dependencies [ $dependentOn ][ $condition ][ $value ] = array ();
}
$this -> _dependencies [ $dependentOn ][ $condition ][ $value ][] = $elementName ;
2006-11-08 06:22:58 +00:00
}
2007-01-12 09:38:02 +00:00
2006-12-19 07:03:08 +00:00
function registerNoSubmitButton ( $buttonname ){
$this -> _noSubmitButtons [] = $buttonname ;
}
2007-01-12 09:38:02 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ param string $buttonname
* @ return mixed
*/
2006-12-19 07:03:08 +00:00
function isNoSubmitButton ( $buttonname ){
return ( array_search ( $buttonname , $this -> _noSubmitButtons ) !== FALSE );
2006-12-04 09:36:30 +00:00
}
2007-01-12 09:38:02 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ param string $buttonname
*/
2006-12-04 09:36:30 +00:00
function _registerCancelButton ( $addfieldsname ){
$this -> _cancelButtons [] = $addfieldsname ;
}
2007-01-12 06:19:39 +00:00
/**
* Displays elements without HTML input tags .
* This method is different to freeze () in that it makes sure no hidden
2008-10-13 19:39:27 +00:00
* elements are included in the form .
* Note : If you want to make sure the submitted value is ignored , please use setDefaults () .
2007-01-12 06:19:39 +00:00
*
2007-01-25 17:59:46 +00:00
* This function also removes all previously defined rules .
*
2007-01-12 06:19:39 +00:00
* @ param mixed $elementList array or string of element ( s ) to be frozen
* @ access public
*/
function hardFreeze ( $elementList = null )
{
if ( ! isset ( $elementList )) {
$this -> _freezeAll = true ;
$elementList = array ();
} else {
if ( ! is_array ( $elementList )) {
$elementList = preg_split ( '/[ ]*,[ ]*/' , $elementList );
}
$elementList = array_flip ( $elementList );
}
foreach ( array_keys ( $this -> _elements ) as $key ) {
$name = $this -> _elements [ $key ] -> getName ();
if ( $this -> _freezeAll || isset ( $elementList [ $name ])) {
$this -> _elements [ $key ] -> freeze ();
$this -> _elements [ $key ] -> setPersistantFreeze ( false );
unset ( $elementList [ $name ]);
2007-01-25 17:59:46 +00:00
// remove all rules
$this -> _rules [ $name ] = array ();
// if field is required, remove the rule
$unset = array_search ( $name , $this -> _required );
if ( $unset !== false ) {
unset ( $this -> _required [ $unset ]);
}
2007-01-12 06:19:39 +00:00
}
}
if ( ! empty ( $elementList )) {
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 );
}
return true ;
2007-08-03 13:08:05 +00:00
}
/**
* Hard freeze all elements in a form except those whose names are in $elementList or hidden elements in a form .
*
* This function also removes all previously defined rules of elements it freezes .
*
2009-05-25 08:27:25 +00:00
* throws HTML_QuickForm_Error
*
2007-08-03 13:08:05 +00:00
* @ param array $elementList array or string of element ( s ) not to be frozen
* @ access public
*/
function hardFreezeAllVisibleExcept ( $elementList )
{
$elementList = array_flip ( $elementList );
foreach ( array_keys ( $this -> _elements ) as $key ) {
$name = $this -> _elements [ $key ] -> getName ();
$type = $this -> _elements [ $key ] -> getType ();
2007-05-28 00:46:11 +00:00
2007-08-03 13:08:05 +00:00
if ( $type == 'hidden' ){
// leave hidden types as they are
} elseif ( ! isset ( $elementList [ $name ])) {
$this -> _elements [ $key ] -> freeze ();
$this -> _elements [ $key ] -> setPersistantFreeze ( false );
// remove all rules
$this -> _rules [ $name ] = array ();
// if field is required, remove the rule
$unset = array_search ( $name , $this -> _required );
if ( $unset !== false ) {
unset ( $this -> _required [ $unset ]);
}
}
}
return true ;
}
/**
* Tells whether the form was already submitted
*
* This is useful since the _submitFiles and _submitValues arrays
* may be completely empty after the trackSubmit value is removed .
*
* @ access public
* @ return bool
*/
function isSubmitted ()
{
return parent :: isSubmitted () && ( ! $this -> isFrozen ());
}
2006-09-24 17:04:51 +00:00
}
2006-11-24 06:39:15 +00:00
2006-09-24 17:04:51 +00:00
/**
2006-10-12 07:33:57 +00:00
* A renderer for MoodleQuickForm that only uses XHTML and CSS and no
2006-09-24 17:04:51 +00:00
* table tags , extends PEAR class HTML_QuickForm_Renderer_Tableless
2006-10-12 07:33:57 +00:00
*
2006-09-24 17:04:51 +00:00
* Stylesheet is part of standard theme and should be automatically included .
*
2009-05-25 08:27:25 +00:00
* @ package moodlecore
* @ copyright Jamie Pratt < me @ jamiep . org >
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
2006-09-24 17:04:51 +00:00
*/
2006-10-12 07:33:57 +00:00
class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless {
2006-09-24 17:04:51 +00:00
/**
* Element template array
* @ var array
* @ access private
*/
var $_elementTemplates ;
2006-09-27 19:12:52 +00:00
/**
* Template used when opening a hidden fieldset
* ( i . e . a fieldset that is opened when there is no header element )
* @ var string
* @ access private
*/
2007-08-03 13:28:03 +00:00
var $_openHiddenFieldsetTemplate = " \n \t <fieldset class= \" hidden \" ><div> " ;
2006-12-14 12:44:10 +00:00
/**
* Header Template string
* @ var string
* @ access private
*/
var $_headerTemplate =
2007-08-03 13:28:03 +00:00
" \n \t \t <legend class= \" ftoggler \" > { header}</legend> \n \t \t <div class= \" advancedbutton \" > { advancedimg} { button}</div><div class= \" fcontainer clearfix \" > \n \t \t " ;
2006-10-12 07:33:57 +00:00
2006-09-27 19:12:52 +00:00
/**
2007-01-30 18:44:23 +00:00
* Template used when opening a fieldset
* @ var string
* @ access private
*/
var $_openFieldsetTemplate = " \n \t <fieldset class= \" clearfix \" { id}> " ;
/**
2006-09-27 19:12:52 +00:00
* Template used when closing a fieldset
* @ var string
* @ access private
*/
2007-08-03 13:28:03 +00:00
var $_closeFieldsetTemplate = " \n \t \t </div></fieldset> " ;
2006-09-27 16:00:19 +00:00
2006-09-27 19:12:52 +00:00
/**
* Required Note template string
* @ var string
* @ access private
*/
2006-10-12 07:33:57 +00:00
var $_requiredNoteTemplate =
2007-01-13 04:54:44 +00:00
" \n \t \t <div class= \" fdescription required \" > { requiredNote}</div> " ;
2006-10-12 07:33:57 +00:00
2006-12-14 12:44:10 +00:00
var $_advancedElements = array ();
/**
* Whether to display advanced elements ( on page load )
*
* @ var integer 1 means show 0 means hide
*/
var $_showAdvanced ;
2006-10-12 07:33:57 +00:00
function MoodleQuickForm_Renderer (){
2006-09-27 16:00:19 +00:00
// switch next two lines for ol li containers for form items.
2007-01-13 04:24:15 +00:00
// $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>');
2007-01-10 05:05:26 +00:00
$this -> _elementTemplates = array (
2007-09-05 14:34:33 +00:00
'default' => " \n \t \t " . '<div class="fitem {advanced}<!-- BEGIN required --> required<!-- END required -->"><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>' ,
2007-01-13 04:24:15 +00:00
2008-04-09 03:45:30 +00:00
'fieldset' => " \n \t \t " . '<div class="fitem {advanced}<!-- BEGIN required --> required<!-- END required -->"><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>' ,
2007-08-03 13:08:05 +00:00
2008-04-09 03:45:30 +00:00
'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>' ,
2007-07-06 04:03:51 +00:00
2008-09-02 12:14:58 +00:00
'warning' => " \n \t \t " . '<div class="fitem {advanced}">{element}</div>' ,
2007-08-03 13:08:05 +00:00
'nodisplay' => '' );
2006-09-24 17:04:51 +00:00
parent :: HTML_QuickForm_Renderer_Tableless ();
}
2006-10-12 07:33:57 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ param array $elements
*/
2006-12-14 12:44:10 +00:00
function setAdvancedElements ( $elements ){
$this -> _advancedElements = $elements ;
}
/**
* What to do when starting the form
*
2009-05-25 08:27:25 +00:00
* @ param object $form MoodleQuickForm
2006-12-14 12:44:10 +00:00
*/
2006-09-24 17:04:51 +00:00
function startForm ( & $form ){
2006-11-22 15:58:07 +00:00
$this -> _reqHTML = $form -> getReqHTML ();
$this -> _elementTemplates = str_replace ( '{req}' , $this -> _reqHTML , $this -> _elementTemplates );
2006-12-14 12:44:10 +00:00
$this -> _advancedHTML = $form -> getAdvancedHTML ();
$this -> _showAdvanced = $form -> getShowAdvanced ();
2006-09-24 17:04:51 +00:00
parent :: startForm ( $form );
2007-08-03 13:08:05 +00:00
if ( $form -> isFrozen ()){
$this -> _formTemplate = " \n <div class= \" mform frozen \" > \n { content} \n </div> " ;
} else {
2009-10-26 21:16:55 +00:00
$this -> _formTemplate = " \n <form { attributes}> \n \t <div style= \" display: none; \" > { hidden}</div> \n { content} \n </form> " ;
2007-08-03 13:08:05 +00:00
$this -> _hiddenHtml .= $form -> _pageparams ;
}
2006-09-24 17:04:51 +00:00
}
2009-11-01 11:31:16 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ param object $group Passed by reference
* @ param mixed $required
* @ param mixed $error
*/
2006-09-24 17:04:51 +00:00
function startGroup ( & $group , $required , $error ){
if ( method_exists ( $group , 'getElementTemplateType' )){
2006-09-27 16:07:37 +00:00
$html = $this -> _elementTemplates [ $group -> getElementTemplateType ()];
2006-09-24 17:04:51 +00:00
} else {
$html = $this -> _elementTemplates [ 'default' ];
2006-10-12 07:33:57 +00:00
2006-09-24 17:04:51 +00:00
}
2006-12-14 12:44:10 +00:00
if ( $this -> _showAdvanced ){
$advclass = ' advanced' ;
} else {
$advclass = ' advanced hide' ;
}
if ( isset ( $this -> _advancedElements [ $group -> getName ()])){
$html = str_replace ( ' {advanced}' , $advclass , $html );
$html = str_replace ( '{advancedimg}' , $this -> _advancedHTML , $html );
} else {
$html = str_replace ( ' {advanced}' , '' , $html );
$html = str_replace ( '{advancedimg}' , '' , $html );
}
2006-09-24 17:04:51 +00:00
if ( method_exists ( $group , 'getHelpButton' )){
$html = str_replace ( '{help}' , $group -> getHelpButton (), $html );
} else {
$html = str_replace ( '{help}' , '' , $html );
}
2006-12-05 14:27:24 +00:00
$html = str_replace ( '{name}' , $group -> getName (), $html );
2006-09-27 19:12:52 +00:00
$html = str_replace ( '{type}' , 'fgroup' , $html );
2006-10-12 07:33:57 +00:00
2006-09-24 17:04:51 +00:00
$this -> _templates [ $group -> getName ()] = $html ;
// Fix for bug in tableless quickforms that didn't allow you to stop a
// fieldset before a group of elements.
// if the element name indicates the end of a fieldset, close the fieldset
if ( in_array ( $group -> getName (), $this -> _stopFieldsetElements )
&& $this -> _fieldsetsOpen > 0
) {
$this -> _html .= $this -> _closeFieldsetTemplate ;
$this -> _fieldsetsOpen -- ;
}
parent :: startGroup ( $group , $required , $error );
}
2009-05-25 08:27:25 +00:00
/**
* @ param object $element
* @ param mixed $required
* @ param mixed $error
*/
2006-09-24 17:04:51 +00:00
function renderElement ( & $element , $required , $error ){
2008-07-31 22:15:30 +00:00
//manipulate id of all elements before rendering
2007-01-08 15:53:17 +00:00
if ( ! is_null ( $element -> getAttribute ( 'id' ))) {
$id = $element -> getAttribute ( 'id' );
} else {
$id = $element -> getName ();
}
//strip qf_ prefix and replace '[' with '_' and strip ']'
$id = preg_replace ( array ( '/^qf_|\]/' , '/\[/' ), array ( '' , '_' ), $id );
if ( strpos ( $id , 'id_' ) !== 0 ){
$element -> updateAttributes ( array ( 'id' => 'id_' . $id ));
}
//adding stuff to place holders in template
2008-07-31 22:15:30 +00:00
//check if this is a group element first
2008-07-09 10:26:13 +00:00
if (( $this -> _inGroup ) and ! empty ( $this -> _groupElementTemplate )) {
2008-09-26 07:24:31 +00:00
// so it gets substitutions for *each* element
2009-12-18 07:42:54 +00:00
$html = $this -> _groupElementTemplate ;
2008-07-09 10:26:13 +00:00
}
elseif ( method_exists ( $element , 'getElementTemplateType' )){
2006-09-24 17:04:51 +00:00
$html = $this -> _elementTemplates [ $element -> getElementTemplateType ()];
} else {
$html = $this -> _elementTemplates [ 'default' ];
2006-12-14 12:44:10 +00:00
}
if ( $this -> _showAdvanced ){
$advclass = ' advanced' ;
} else {
$advclass = ' advanced hide' ;
}
if ( isset ( $this -> _advancedElements [ $element -> getName ()])){
$html = str_replace ( ' {advanced}' , $advclass , $html );
} else {
$html = str_replace ( ' {advanced}' , '' , $html );
}
if ( isset ( $this -> _advancedElements [ $element -> getName ()]) || $element -> getName () == 'mform_showadvanced' ){
$html = str_replace ( '{advancedimg}' , $this -> _advancedHTML , $html );
} else {
$html = str_replace ( '{advancedimg}' , '' , $html );
2006-09-24 17:04:51 +00:00
}
2006-09-27 19:12:52 +00:00
$html = str_replace ( '{type}' , 'f' . $element -> getType (), $html );
2006-12-05 14:27:24 +00:00
$html = str_replace ( '{name}' , $element -> getName (), $html );
2006-09-24 17:04:51 +00:00
if ( method_exists ( $element , 'getHelpButton' )){
2006-11-22 15:58:07 +00:00
$html = str_replace ( '{help}' , $element -> getHelpButton (), $html );
2006-09-24 17:04:51 +00:00
} else {
2006-11-22 15:58:07 +00:00
$html = str_replace ( '{help}' , '' , $html );
2006-10-12 07:33:57 +00:00
2006-09-24 17:04:51 +00:00
}
2008-07-09 10:26:13 +00:00
if (( $this -> _inGroup ) and ! empty ( $this -> _groupElementTemplate )) {
$this -> _groupElementTemplate = $html ;
2007-09-18 09:35:44 +00:00
}
2008-07-09 10:26:13 +00:00
elseif ( ! isset ( $this -> _templates [ $element -> getName ()])) {
$this -> _templates [ $element -> getName ()] = $html ;
2008-07-31 22:15:30 +00:00
}
2006-09-24 17:04:51 +00:00
parent :: renderElement ( $element , $required , $error );
}
2006-12-14 12:44:10 +00:00
2009-05-25 08:27:25 +00:00
/**
* @ param object $form Passed by reference
*/
2006-11-08 06:22:58 +00:00
function finishForm ( & $form ){
2007-08-03 13:08:05 +00:00
if ( $form -> isFrozen ()){
$this -> _hiddenHtml = '' ;
}
2006-11-08 06:22:58 +00:00
parent :: finishForm ( $form );
2007-08-03 13:08:05 +00:00
if (( ! $form -> isFrozen ()) && ( '' != ( $script = $form -> getLockOptionEndScript ()))) {
// add a lockoptions script
2006-11-08 06:22:58 +00:00
$this -> _html = $this -> _html . " \n " . $script ;
}
}
2006-12-14 12:44:10 +00:00
/**
* Called when visiting a header element
*
2009-05-25 08:27:25 +00:00
* @ param object $header An HTML_QuickForm_header element being visited
2006-12-14 12:44:10 +00:00
* @ access public
* @ return void
*/
2009-06-15 05:37:57 +00:00
function renderHeader ( & $header ) {
global $PAGE ;
2009-06-29 01:58:11 +00:00
static $advformcount ;
// This ensures that if 2(+) advanced buttons are used
// that all show/hide buttons appear in the correct place
// Because of now using $PAGE->requires->js_function_call
if ( $advformcount == null ) {
$advformcount = 1 ;
}
2006-12-14 12:44:10 +00:00
$name = $header -> getName ();
$id = empty ( $name ) ? '' : ' id="' . $name . '"' ;
2007-01-10 06:17:45 +00:00
$id = preg_replace ( array ( '/\]/' , '/\[/' ), array ( '' , '_' ), $id );
2006-12-14 12:44:10 +00:00
if ( is_null ( $header -> _text )) {
$header_html = '' ;
} elseif ( ! empty ( $name ) && isset ( $this -> _templates [ $name ])) {
$header_html = str_replace ( '{header}' , $header -> toHtml (), $this -> _templates [ $name ]);
} else {
$header_html = str_replace ( '{header}' , $header -> toHtml (), $this -> _headerTemplate );
}
if ( isset ( $this -> _advancedElements [ $name ])){
$header_html = str_replace ( '{advancedimg}' , $this -> _advancedHTML , $header_html );
} else {
$header_html = str_replace ( '{advancedimg}' , '' , $header_html );
}
$elementName = 'mform_showadvanced' ;
if ( $this -> _showAdvanced == 0 ){
$buttonlabel = get_string ( 'showadvanced' , 'form' );
} else {
$buttonlabel = get_string ( 'hideadvanced' , 'form' );
}
if ( isset ( $this -> _advancedElements [ $name ])){
2009-12-16 20:25:14 +00:00
$PAGE -> requires -> yui2_lib ( 'event' );
2007-11-17 13:30:15 +00:00
// this is tricky - the first submit button on form is "clicked" if user presses enter
// we do not want to "submit" using advanced button if javascript active
2009-06-29 01:58:11 +00:00
$button_nojs = '<input name="' . $elementName . '" id="' . $elementName . ( string ) $advformcount . '" class="showadvancedbtn" value="' . $buttonlabel . '" type="submit" />' ;
2008-08-28 07:52:09 +00:00
$buttonlabel = addslashes_js ( $buttonlabel );
2009-06-29 02:10:49 +00:00
$PAGE -> requires -> string_for_js ( 'showadvanced' , 'form' );
$PAGE -> requires -> string_for_js ( 'hideadvanced' , 'form' );
$PAGE -> requires -> js_function_call ( 'showAdvancedInit' , Array ( $elementName . ( string ) $advformcount , $elementName , $buttonlabel ));
2009-11-01 11:31:16 +00:00
2009-06-29 01:58:11 +00:00
$advformcount ++ ;
$header_html = str_replace ( '{button}' , $button_nojs , $header_html );
2006-12-14 12:44:10 +00:00
} else {
2007-11-17 13:30:15 +00:00
$header_html = str_replace ( '{button}' , '' , $header_html );
2006-12-14 12:44:10 +00:00
}
if ( $this -> _fieldsetsOpen > 0 ) {
$this -> _html .= $this -> _closeFieldsetTemplate ;
$this -> _fieldsetsOpen -- ;
}
$openFieldsetTemplate = str_replace ( '{id}' , $id , $this -> _openFieldsetTemplate );
if ( $this -> _showAdvanced ){
$advclass = ' class="advanced"' ;
} else {
$advclass = ' class="advanced hide"' ;
}
if ( isset ( $this -> _advancedElements [ $name ])){
$openFieldsetTemplate = str_replace ( '{advancedclass}' , $advclass , $openFieldsetTemplate );
} else {
$openFieldsetTemplate = str_replace ( '{advancedclass}' , '' , $openFieldsetTemplate );
}
$this -> _html .= $openFieldsetTemplate . $header_html ;
$this -> _fieldsetsOpen ++ ;
} // end func renderHeader
function getStopFieldsetElements (){
return $this -> _stopFieldsetElements ;
}
2006-09-24 17:04:51 +00:00
}
2009-05-25 08:27:25 +00:00
/**
* @ global object $GLOBALS [ '_HTML_QuickForm_default_renderer' ]
* @ name $_HTML_QuickForm_default_renderer
*/
2009-07-02 14:58:41 +00:00
$GLOBALS [ '_HTML_QuickForm_default_renderer' ] = new MoodleQuickForm_Renderer ();
2006-09-24 17:04:51 +00:00
2009-05-25 08:27:25 +00:00
/** Please keep this list in alphabetical order. */
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'advcheckbox' , " $CFG->libdir /form/advcheckbox.php " , 'MoodleQuickForm_advcheckbox' );
MoodleQuickForm :: registerElementType ( 'button' , " $CFG->libdir /form/button.php " , 'MoodleQuickForm_button' );
MoodleQuickForm :: registerElementType ( 'cancel' , " $CFG->libdir /form/cancel.php " , 'MoodleQuickForm_cancel' );
2009-11-05 07:06:09 +00:00
MoodleQuickForm :: registerElementType ( 'searchableselector' , " $CFG->libdir /form/searchableselector.php " , 'MoodleQuickForm_searchableselector' );
2006-10-12 07:33:57 +00:00
MoodleQuickForm :: registerElementType ( 'checkbox' , " $CFG->libdir /form/checkbox.php " , 'MoodleQuickForm_checkbox' );
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'date_selector' , " $CFG->libdir /form/dateselector.php " , 'MoodleQuickForm_date_selector' );
MoodleQuickForm :: registerElementType ( 'date_time_selector' , " $CFG->libdir /form/datetimeselector.php " , 'MoodleQuickForm_date_time_selector' );
2009-03-10 06:46:34 +00:00
MoodleQuickForm :: registerElementType ( 'duration' , " $CFG->libdir /form/duration.php " , 'MoodleQuickForm_duration' );
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'editor' , " $CFG->libdir /form/editor.php " , 'MoodleQuickForm_editor' );
2006-10-12 07:33:57 +00:00
MoodleQuickForm :: registerElementType ( 'file' , " $CFG->libdir /form/file.php " , 'MoodleQuickForm_file' );
2008-11-19 20:27:18 +00:00
MoodleQuickForm :: registerElementType ( 'filemanager' , " $CFG->libdir /form/filemanager.php " , 'MoodleQuickForm_filemanager' );
2008-07-31 02:51:28 +00:00
MoodleQuickForm :: registerElementType ( 'filepicker' , " $CFG->libdir /form/filepicker.php " , 'MoodleQuickForm_filepicker' );
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'format' , " $CFG->libdir /form/format.php " , 'MoodleQuickForm_format' );
2006-10-12 07:33:57 +00:00
MoodleQuickForm :: registerElementType ( 'group' , " $CFG->libdir /form/group.php " , 'MoodleQuickForm_group' );
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'header' , " $CFG->libdir /form/header.php " , 'MoodleQuickForm_header' );
MoodleQuickForm :: registerElementType ( 'hidden' , " $CFG->libdir /form/hidden.php " , 'MoodleQuickForm_hidden' );
MoodleQuickForm :: registerElementType ( 'htmleditor' , " $CFG->libdir /form/htmleditor.php " , 'MoodleQuickForm_htmleditor' );
MoodleQuickForm :: registerElementType ( 'modgrade' , " $CFG->libdir /form/modgrade.php " , 'MoodleQuickForm_modgrade' );
MoodleQuickForm :: registerElementType ( 'modvisible' , " $CFG->libdir /form/modvisible.php " , 'MoodleQuickForm_modvisible' );
2006-10-12 07:33:57 +00:00
MoodleQuickForm :: registerElementType ( 'password' , " $CFG->libdir /form/password.php " , 'MoodleQuickForm_password' );
2007-08-03 13:08:05 +00:00
MoodleQuickForm :: registerElementType ( 'passwordunmask' , " $CFG->libdir /form/passwordunmask.php " , 'MoodleQuickForm_passwordunmask' );
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'questioncategory' , " $CFG->libdir /form/questioncategory.php " , 'MoodleQuickForm_questioncategory' );
2006-10-12 07:33:57 +00:00
MoodleQuickForm :: registerElementType ( 'radio' , " $CFG->libdir /form/radio.php " , 'MoodleQuickForm_radio' );
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'recaptcha' , " $CFG->libdir /form/recaptcha.php " , 'MoodleQuickForm_recaptcha' );
2006-10-12 07:33:57 +00:00
MoodleQuickForm :: registerElementType ( 'select' , " $CFG->libdir /form/select.php " , 'MoodleQuickForm_select' );
2007-08-03 13:08:05 +00:00
MoodleQuickForm :: registerElementType ( 'selectgroups' , " $CFG->libdir /form/selectgroups.php " , 'MoodleQuickForm_selectgroups' );
2009-01-14 09:58:12 +00:00
MoodleQuickForm :: registerElementType ( 'selectwithlink' , " $CFG->libdir /form/selectwithlink.php " , 'MoodleQuickForm_selectwithlink' );
MoodleQuickForm :: registerElementType ( 'selectyesno' , " $CFG->libdir /form/selectyesno.php " , 'MoodleQuickForm_selectyesno' );
MoodleQuickForm :: registerElementType ( 'static' , " $CFG->libdir /form/static.php " , 'MoodleQuickForm_static' );
MoodleQuickForm :: registerElementType ( 'submit' , " $CFG->libdir /form/submit.php " , 'MoodleQuickForm_submit' );
2007-12-04 10:35:25 +00:00
MoodleQuickForm :: registerElementType ( 'submitlink' , " $CFG->libdir /form/submitlink.php " , 'MoodleQuickForm_submitlink' );
2009-01-15 09:24:45 +00:00
MoodleQuickForm :: registerElementType ( 'tags' , " $CFG->libdir /form/tags.php " , 'MoodleQuickForm_tags' );
2006-10-12 07:33:57 +00:00
MoodleQuickForm :: registerElementType ( 'text' , " $CFG->libdir /form/text.php " , 'MoodleQuickForm_text' );
MoodleQuickForm :: registerElementType ( 'textarea' , " $CFG->libdir /form/textarea.php " , 'MoodleQuickForm_textarea' );
2009-10-13 08:31:50 +00:00
MoodleQuickForm :: registerElementType ( 'url' , " $CFG->libdir /form/url.php " , 'MoodleQuickForm_url' );
2008-09-02 12:14:58 +00:00
MoodleQuickForm :: registerElementType ( 'warning' , " $CFG->libdir /form/warning.php " , 'MoodleQuickForm_warning' );