MDL-33682 backup: cope with sections called '0'
[moodle.git] / backup / util / ui / backup_ui_setting.class.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * This file contains the setting user interface classes that all backup/restore
20  * settings use to represent the UI they have.
21  *
22  * @package   moodlecore
23  * @copyright 2010 Sam Hemelryk
24  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
27 /**
28  * Abstract class used to represent the user interface that a setting has.
29  *
30  * @todo extend as required for restore
31  * @copyright 2010 Sam Hemelryk
32  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33  */
34 class base_setting_ui {
35     /**
36      * Prefix applied to all inputs/selects
37      */
38     const NAME_PREFIX = 'setting_';
39     /**
40      * The name of the setting
41      * @var string
42      */
43     protected $name;
44     /**
45      * The label for the setting
46      * @var string
47      */
48     protected $label;
49     /**
50      * An array of HTML attributes to apply to this setting
51      * @var array
52      */
53     protected $attributes = array();
54     /**
55      * The backup_setting UI type this relates to. One of backup_setting::UI_*;
56      * @var int
57      */
58     protected $type;
59     /**
60      * An icon to display next to this setting in the UI
61      * @var pix_icon
62      */
63     protected $icon = false;
64     /**
65      * The setting this UI belongs to (parent reference)
66      * @var base_setting|backup_setting
67      */
68     protected $setting;
69     /**
70      * Constructors are sooooo cool
71      * @param base_setting $setting
72      */
73     public function __construct(base_setting $setting) {
74         $this->setting = $setting;
75     }
77     /**
78      * Destroy all circular references. It helps PHP 5.2 a lot!
79      */
80     public function destroy() {
81         // No need to destroy anything recursively here, direct reset
82         $this->setting = null;
83     }
85     /**
86      * Gets the name of this item including its prefix
87      * @return string
88      */
89     public function get_name() {
90         return self::NAME_PREFIX.$this->name;
91     }
92     /**
93      * Gets the name of this item including its prefix
94      * @return string
95      */
96     public function get_label() {
97         return $this->label;
98     }
99     /**
100      * Gets the type of this element
101      * @return int
102      */
103     public function get_type() {
104         return $this->type;
105     }
106     /**
107      * Gets the HTML attributes for this item
108      * @return array
109      */
110     public function get_attributes() {
111         return $this->attributes;
112     }
113     /**
114      * Gets the value of this setting
115      * @return mixed
116      */
117     public function get_value() {
118         return $this->setting->get_value();
119     }
120     /**
121      * Gets the value to display in a static quickforms element
122      * @return mixed
123      */
124     public function get_static_value() {
125         return $this->setting->get_value();
126     }
127     /**
128      * Sets the label
129      * @param string $label
130      */
131     public function set_label($label) {
132         if ((string)$label === '' || $label !== clean_param($label, PARAM_TEXT)) {
133             throw new base_setting_ui_exception('setting_invalid_ui_label');
134         }
135         $this->label = $label;
136     }
137     /**
138      * Disables the UI for this element
139      */
140     public function disable() {
141        $this->attributes['disabled'] = 'disabled';
142     }
144     /**
145      * Sets the icon to display next to this item
146      *
147      * @param pix_icon $icon
148      */
149     public function set_icon(pix_icon $icon) {
150         $this->icon = $icon;
151     }
153     /**
154      * Returns the icon to display next to this item, or false if there isn't one.
155      *
156      * @return pix_icon|false
157      */
158     public function get_icon() {
159         if (!empty($this->icon)) {
160             return $this->icon;
161         }
162         return false;
163     }
166 /**
167  * Abstract class to represent the user interface backup settings have
168  *
169  * @copyright 2010 Sam Hemelryk
170  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
171  */
172 abstract class backup_setting_ui extends base_setting_ui {
173     /**
174      * An array of options relating to this setting
175      * @var array
176      */
177     protected $options = array();
179     /**
180      * JAC... Just Another Constructor
181      *
182      * @param backup_setting $setting
183      * @param string|null $label The label to display with the setting ui
184      * @param array|null $attributes Array of HTML attributes to apply to the element
185      * @param array|null $options Array of options to apply to the setting ui object
186      */
187     public function __construct(backup_setting $setting, $label = null, array $attributes = null, array $options = null) {
188         parent::__construct($setting);
189         // Improve the inputs name by appending the level to the name
190         switch ($setting->get_level()) {
191             case backup_setting::ROOT_LEVEL :
192                 $this->name = 'root_'.$setting->get_name();
193                 break;
194             case backup_setting::COURSE_LEVEL :
195                 $this->name = 'course_'.$setting->get_name();
196                 break;
197             case backup_setting::SECTION_LEVEL :
198                 $this->name = 'section_'.$setting->get_name();
199                 break;
200             case backup_setting::ACTIVITY_LEVEL :
201                 $this->name = 'activity_'.$setting->get_name();
202                 break;
203         }
204         $this->label = $label;
205         if (is_array($attributes)) {
206             $this->attributes = $attributes;
207         }
208         if (is_array($options)) {
209             $this->options = $options;
210         }
211     }
212     /**
213      * Creates a new backup setting ui based on the setting it is given
214      *
215      * Throws an exception if an invalid type is provided.
216      *
217      * @param backup_setting $setting
218      * @param int $type The backup_setting UI type. One of backup_setting::UI_*;
219      * @param string $label The label to display with the setting ui
220      * @param array $attributes Array of HTML attributes to apply to the element
221      * @param array $options Array of options to apply to the setting ui object
222      *
223      * @return backup_setting_ui_text|backup_setting_ui_checkbox|backup_setting_ui_select|backup_setting_ui_radio
224      */
225     final public static function make(backup_setting $setting, $type, $label, array $attributes = null, array $options=null) {
226         // Base the decision we make on the type that was sent
227         switch ($type) {
228             case backup_setting::UI_HTML_CHECKBOX :
229                 return new backup_setting_ui_checkbox($setting, $label, null, (array)$attributes, (array)$options);
230             case backup_setting::UI_HTML_DROPDOWN :
231                 return new backup_setting_ui_select($setting, $label, null, (array)$attributes, (array)$options);
232             case backup_setting::UI_HTML_RADIOBUTTON :
233                 return new backup_setting_ui_radio($setting, $label, null, null, (array)$attributes, (array)$options);
234             case backup_setting::UI_HTML_TEXTFIELD :
235                 return new backup_setting_ui_text($setting, $label, $attributes, $options);
236             default:
237                 throw new backup_setting_ui_exception('setting_invalid_ui_type');
238         }
239     }
240     /**
241      * Get element properties that can be used to make a quickform element
242      * @return array
243      */
244     abstract public function get_element_properties(base_task $task=null, renderer_base $output=null);
245     /**
246      * Applies config options to a given properties array and then returns it
247      * @param array $properties
248      * @return array
249      */
250     public function apply_options(array $properties) {
251         if (!empty($this->options['size'])) {
252             $properties['attributes']['size'] = $this->options['size'];
253         }
254         return $properties;
255     }
256     /**
257      * Gets the label for this item
258      * @param backup_task|null $task Optional, if provided and the setting is an include
259      *          $task is used to set the setting label
260      * @return string
261      */
262     public function get_label(base_task $task=null) {
263         // If a task has been provided and the label is not already set meaniningfully
264         // we will attempt to improve it.
265         if (!is_null($task) && $this->label == $this->setting->get_name() && strpos($this->setting->get_name(), '_include')!==false) {
266             if ($this->setting->get_level() == backup_setting::SECTION_LEVEL) {
267                 $this->label = get_string('includesection', 'backup', $task->get_name());
268             } else if ($this->setting->get_level() == backup_setting::ACTIVITY_LEVEL) {
269                 $this->label = $task->get_name();
270             }
271         }
272         return $this->label;
273     }
274     /**
275      * Returns true if the setting is changeable.
276      *
277      * A setting is changeable if it meets either of the two following conditions.
278      *
279      * 1. The setting is not locked
280      * 2. The setting is locked but only by settings that are of the same level (same page)
281      *
282      * Condition 2 is really why we have this function
283      *
284      * @return bool
285      */
286     public function is_changeable() {
287         if ($this->setting->get_status() === backup_setting::NOT_LOCKED) {
288             // Its not locked so its chanegable
289             return true;
290         } else if ($this->setting->get_status() !== backup_setting::LOCKED_BY_HIERARCHY) {
291             // Its not changeable because its locked by permission or config
292             return false;
293         } else if ($this->setting->has_dependencies_on_settings()) {
294             foreach ($this->setting->get_settings_depended_on() as $dependency) {
295                 if ($dependency->is_locked() && $dependency->get_setting()->get_level() !== $this->setting->get_level()) {
296                     // Its not changeable because one or more dependancies arn't
297                     // changeable.
298                    return false;
299                 }
300             }
301             // Its changeable because all dependencies are changeable.
302             return true;
303         }
304         // We should never get here but if we do return false to be safe.
305         // The setting would need to be locked by hierarchy and not have any deps
306         return false;
307     }
311 /**
312  * A text input user interface element for backup settings
313  *
314  * @copyright 2010 Sam Hemelryk
315  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
316  */
317 class backup_setting_ui_text extends backup_setting_ui {
318     /**
319      * @var int
320      */
321     protected $type = backup_setting::UI_HTML_TEXTFIELD;
322     /**
323      * Returns an array of properties suitable for generating a quickforms element
324      * @param backup_task|null $task
325      * @return array (element, name, label, attributes)
326      */
327     public function get_element_properties(base_task $task=null, renderer_base $output=null) {
328         // name, label, text, attributes
329         $icon = $this->get_icon();
330         $label = $this->get_label($task);
331         if (!empty($icon)) {
332             $label .= '&nbsp;'.$output->render($icon);
333         }
334         // name, label, attributes
335         return $this->apply_options(array('element'=>'text','name'=>self::NAME_PREFIX.$this->name, 'label'=>$label, 'attributes'=>$this->attributes));
336     }
340 /**
341  * A checkbox user interface element for backup settings (default)
342  *
343  * @copyright 2010 Sam Hemelryk
344  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
345  */
346 class backup_setting_ui_checkbox extends backup_setting_ui {
347     /**
348      * @var int
349      */
350     protected $type = backup_setting::UI_HTML_CHECKBOX;
351     /**
352      * @var bool
353      */
354     protected $changeable = true;
355     /**
356      * The text to show next to the checkbox
357      * @var string
358      */
359     protected $text;
360     /**
361      * Overridden constructor so we can take text argument
362      * @param backup_setting $setting
363      * @param string $label
364      * @param string $text
365      * @param array $attributes
366      * @param array $options
367      */
368     public function __construct(backup_setting $setting, $label = null, $text=null, array $attributes = array(), array $options = array()) {
369         parent::__construct($setting, $label, $attributes, $options);
370         $this->text = $text;
371     }
372     /**
373      * Returns an array of properties suitable for generating a quickforms element
374      * @param backup_task|null $task
375      * @return array (element, name, label, text, attributes);
376      */
377     public function get_element_properties(base_task $task=null, renderer_base $output=null) {
378         // name, label, text, attributes
380         $icon = $this->get_icon();
381         $label = $this->get_label($task);
382         if (!empty($icon)) {
383             $label .= '&nbsp;'.$output->render($icon);
384         }
385         return $this->apply_options(array('element'=>'checkbox','name'=>self::NAME_PREFIX.$this->name, 'label'=>$label, 'text'=>$this->text, 'attributes'=>$this->attributes));
386     }
387     /**
388      * Sets the text for the element
389      * @param string $text
390      */
391     public function set_text($text) {
392         $this->text = $text;
393     }
394     /**
395      * Gets the static value for the element
396      * @global core_renderer $OUTPUT
397      * @return string
398      */
399     public function get_static_value() {
400         global $OUTPUT;
401         // Checkboxes are always yes or no
402         if ($this->get_value()) {
403             return $OUTPUT->pix_icon('i/tick_green_big', get_string('yes'));
404         } else {
405             return $OUTPUT->pix_icon('i/cross_red_big', get_string('no'));
406         }
407     }
409     /**
410      * Returns true if the setting is changeable
411      * @return bool
412      */
413     public function is_changeable() {
414         if ($this->changeable===false) {
415             return false;
416         } else {
417             return parent::is_changeable();
418         }
419     }
421     /**
422      * Sets whether the setting is changeable,
423      * Note dependencies can still mark this setting changeable or not
424      * @param bool $newvalue
425      */
426     public function set_changeable($newvalue) {
427         $this->changeable = ($newvalue);
428     }
431 /**
432  * Radio button user interface element for backup settings
433  *
434  * @copyright 2010 Sam Hemelryk
435  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
436  */
437 class backup_setting_ui_radio extends backup_setting_ui {
438     /**
439      * @var int
440      */
441     protected $type = backup_setting::UI_HTML_RADIOBUTTON;
442     /**
443      * The string shown next to the input
444      * @var string
445      */
446     protected $text;
447     /**
448      * The value for the radio input
449      * @var string
450      */
451     protected $value;
452     /**
453      *
454      * @param backup_setting $setting
455      * @param string $label
456      * @param string $text
457      * @param string $value
458      * @param array $attributes
459      * @param array $options
460      */
461     public function __construct(backup_setting $setting, $label = null, $text=null, $value=null, array $attributes = array(), array $options = array()) {
462         parent::__construct($setting, $label, $attributes, $options);
463         $this->text = $text;
464         $this->value = (string)$value;
465     }
466     /**
467      * Returns an array of properties suitable for generating a quickforms element
468      * @param backup_task|null $task
469      * @return array (element, name, label, text, value, attributes)
470      */
471     public function get_element_properties(base_task $task=null, renderer_base $output=null) {
472         // name, label, text, attributes
473         $icon = $this->get_icon();
474         $label = $this->get_label($task);
475         if (!empty($icon)) {
476             $label .= '&nbsp;'.$output->render($icon);
477         }
478         // name, label, text, value, attributes
479         return $this->apply_options(array('element'=>'radio','name'=>self::NAME_PREFIX.$this->name, 'label'=>$label, 'text'=>$this->text, 'value'=>$this->value, 'attributes'=>$this->attributes));
480     }
481     /**
482      * Sets the text next to this input
483      * @param text $text
484      */
485     public function set_text($text) {
486         $this->text = $text;
487     }
488     /**
489      * Sets the value for the input
490      * @param string $value
491      */
492     public function set_value($value) {
493         $this->value = (string)$value;
494     }
495     /**
496      * Gets the static value to show for the element
497      */
498     public function get_static_value() {
499         return $this->value;
500     }
503 /**
504  * A select box, drop down user interface for backup settings
505  *
506  * @copyright 2010 Sam Hemelryk
507  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
508  */
509 class backup_setting_ui_select extends backup_setting_ui {
510     /**
511      * @var int
512      */
513     protected $type = backup_setting::UI_HTML_DROPDOWN;
514     /**
515      * An array of options to display in the select
516      * @var array
517      */
518     protected $values;
519     /**
520      *
521      * @param backup_setting $setting
522      * @param string $label
523      * @param array $values
524      * @param array $attributes
525      * @param array $options
526      */
527     public function __construct(backup_setting $setting, $label = null, $values=null, array $attributes = array(), array $options = array()) {
528         parent::__construct($setting, $label, $attributes, $options);
529         $this->values = $values;
530     }
531     /**
532      * Returns an array of properties suitable for generating a quickforms element
533      * @param backup_task|null $task
534      * @return array (element, name, label, options, attributes)
535      */
536     public function get_element_properties(base_task $task = null, renderer_base $output=null) {
537         // name, label, text, attributes
538         $icon = $this->get_icon();
539         $label = $this->get_label($task);
540         if (!empty($icon)) {
541             $label .= '&nbsp;'.$output->render($icon);
542         }
543         // name, label, options, attributes
544         return $this->apply_options(array('element'=>'select','name'=>self::NAME_PREFIX.$this->name, 'label'=>$label, 'options'=>$this->values, 'attributes'=>$this->attributes));
545     }
546     /**
547      * Sets the options for the select box
548      * @param array $values Associative array of value=>text options
549      */
550     public function set_values(array $values) {
551         $this->values = $values;
552     }
553     /**
554      * Gets the static value for this select element
555      * @return string
556      */
557     public function get_static_value() {
558         return $this->values[$this->get_value()];
559     }
560     /**
561      * Returns true if the setting is changeable, false otherwise
562      *
563      * @return bool
564      */
565     public function is_changeable() {
566         if (count($this->values) == 1) {
567             return false;
568         } else {
569             return parent::is_changeable();
570         }
571     }
574 class backup_setting_ui_dateselector extends backup_setting_ui_text {
575     public function get_element_properties(base_task $task = null, renderer_base $output=null) {
576         if (!array_key_exists('optional', $this->attributes)) {
577             $this->attributes['optional'] = false;
578         }
579         $properties = parent::get_element_properties($task, $output);
580         $properties['element'] = 'date_selector';
581         return $properties;
582     }
583     public function get_static_value() {
584         $value = $this->get_value();
585         if (!empty($value)) {
586             return userdate($value);
587         }
588         return parent::get_static_value();
589     }
592 class base_setting_ui_exception extends base_setting_exception {}
593 class backup_setting_ui_exception extends base_setting_ui_exception {};