MDL-72762 backup: Accept empty and whitespace-only UI labels.
[moodle.git] / backup / util / ui / backup_ui_setting.class.php
blobd5f8287f01e2bfe582ee040736fcb0aff8e649b7
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * This file contains the setting user interface classes that all backup/restore
19 * settings use to represent the UI they have.
21 * @package core_backup
22 * @copyright 2010 Sam Hemelryk
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 /**
27 * Abstract class used to represent the user interface that a setting has.
29 * @todo extend as required for restore
30 * @package core_backup
31 * @copyright 2010 Sam Hemelryk
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34 class base_setting_ui {
35 /**
36 * Prefix applied to all inputs/selects
38 const NAME_PREFIX = 'setting_';
39 /**
40 * The name of the setting
41 * @var string
43 protected $name;
44 /**
45 * The label for the setting
46 * @var string
48 protected $label;
49 /**
50 * An array of HTML attributes to apply to this setting
51 * @var array
53 protected $attributes = array();
54 /**
55 * The backup_setting UI type this relates to. One of backup_setting::UI_*;
56 * @var int
58 protected $type;
59 /**
60 * An icon to display next to this setting in the UI
61 * @var pix_icon
63 protected $icon = false;
64 /**
65 * The setting this UI belongs to (parent reference)
66 * @var base_setting|backup_setting
68 protected $setting;
70 /**
71 * Constructors are sooooo cool
72 * @param base_setting $setting
74 public function __construct(base_setting $setting) {
75 $this->setting = $setting;
78 /**
79 * Destroy all circular references. It helps PHP 5.2 a lot!
81 public function destroy() {
82 // No need to destroy anything recursively here, direct reset.
83 $this->setting = null;
86 /**
87 * Gets the name of this item including its prefix
88 * @return string
90 public function get_name() {
91 return self::NAME_PREFIX.$this->name;
94 /**
95 * Gets the name of this item including its prefix
96 * @return string
98 public function get_label() {
99 return $this->label;
103 * Gets the type of this element
104 * @return int
106 public function get_type() {
107 return $this->type;
111 * Gets the HTML attributes for this item
112 * @return array
114 public function get_attributes() {
115 return $this->attributes;
119 * Gets the value of this setting
120 * @return mixed
122 public function get_value() {
123 return $this->setting->get_value();
127 * Gets the value to display in a static quickforms element
128 * @return mixed
130 public function get_static_value() {
131 return $this->setting->get_value();
135 * Gets the the PARAM_XXXX validation to be applied to the setting
137 * return string The PARAM_XXXX constant of null if the setting type is not defined
139 public function get_param_validation() {
140 return $this->setting->get_param_validation();
144 * Sets the label.
146 * @throws base_setting_ui_exception when the label is not valid.
147 * @param string $label
149 public function set_label(string $label): void {
150 // Let's avoid empty/whitespace-only labels, so the html clean (that makes trim()) doesn't fail.
151 if (trim($label) === '') {
152 $label = '&nbsp;'; // Will be converted to non-breaking utf-8 char 0xc2a0 by PARAM_CLEANHTML.
155 $label = clean_param($label, PARAM_CLEANHTML);
157 if ($label === '') {
158 throw new base_setting_ui_exception('setting_invalid_ui_label');
161 $this->label = $label;
165 * Disables the UI for this element
167 public function disable() {
168 $this->attributes['disabled'] = 'disabled';
172 * Sets the icon to display next to this item
174 * @param pix_icon $icon
176 public function set_icon(pix_icon $icon) {
177 $this->icon = $icon;
181 * Returns the icon to display next to this item, or false if there isn't one.
183 * @return pix_icon|false
185 public function get_icon() {
186 if (!empty($this->icon)) {
187 return $this->icon;
189 return false;
194 * Abstract class to represent the user interface backup settings have
196 * @package core_backup
197 * @copyright 2010 Sam Hemelryk
198 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
200 abstract class backup_setting_ui extends base_setting_ui {
202 * An array of options relating to this setting
203 * @var array
205 protected $options = array();
208 * JAC... Just Another Constructor
210 * @param backup_setting $setting
211 * @param string $label The label to display with the setting ui
212 * @param array $attributes Array of HTML attributes to apply to the element
213 * @param array $options Array of options to apply to the setting ui object
215 public function __construct(backup_setting $setting, $label = null, array $attributes = null, array $options = null) {
216 parent::__construct($setting);
217 // Improve the inputs name by appending the level to the name.
218 switch ($setting->get_level()) {
219 case backup_setting::ROOT_LEVEL :
220 $this->name = 'root_'.$setting->get_name();
221 break;
222 case backup_setting::COURSE_LEVEL :
223 $this->name = 'course_'.$setting->get_name();
224 break;
225 case backup_setting::SECTION_LEVEL :
226 $this->name = 'section_'.$setting->get_name();
227 break;
228 case backup_setting::ACTIVITY_LEVEL :
229 $this->name = 'activity_'.$setting->get_name();
230 break;
232 $this->label = $label;
233 if (is_array($attributes)) {
234 $this->attributes = $attributes;
236 if (is_array($options)) {
237 $this->options = $options;
242 * Creates a new backup setting ui based on the setting it is given
244 * @throws backup_setting_ui_exception if the setting type is not supported,
245 * @param backup_setting $setting
246 * @param int $type The backup_setting UI type. One of backup_setting::UI_*;
247 * @param string $label The label to display with the setting ui
248 * @param array $attributes Array of HTML attributes to apply to the element
249 * @param array $options Array of options to apply to the setting ui object
250 * @return backup_setting_ui_text|backup_setting_ui_checkbox|backup_setting_ui_select|backup_setting_ui_radio
252 final public static function make(backup_setting $setting, $type, $label, array $attributes = null, array $options = null) {
253 // Base the decision we make on the type that was sent.
254 switch ($type) {
255 case backup_setting::UI_HTML_CHECKBOX :
256 return new backup_setting_ui_checkbox($setting, $label, null, (array)$attributes, (array)$options);
257 case backup_setting::UI_HTML_DROPDOWN :
258 return new backup_setting_ui_select($setting, $label, null, (array)$attributes, (array)$options);
259 case backup_setting::UI_HTML_RADIOBUTTON :
260 return new backup_setting_ui_radio($setting, $label, null, null, (array)$attributes, (array)$options);
261 case backup_setting::UI_HTML_TEXTFIELD :
262 return new backup_setting_ui_text($setting, $label, $attributes, $options);
263 default:
264 throw new backup_setting_ui_exception('setting_invalid_ui_type');
269 * Get element properties that can be used to make a quickform element
271 * @param base_task $task
272 * @param renderer_base $output
273 * @return array
275 abstract public function get_element_properties(base_task $task = null, renderer_base $output = null);
278 * Applies config options to a given properties array and then returns it
279 * @param array $properties
280 * @return array
282 public function apply_options(array $properties) {
283 if (!empty($this->options['size'])) {
284 $properties['attributes']['size'] = $this->options['size'];
286 return $properties;
290 * Gets the label for this item
291 * @param base_task $task Optional, if provided and the setting is an include
292 * $task is used to set the setting label
293 * @return string
295 public function get_label(base_task $task = null) {
296 // If a task has been provided and the label is not already set meaningfully
297 // we will attempt to improve it.
298 if (!is_null($task) && $this->label == $this->setting->get_name() && strpos($this->setting->get_name(), '_include') !== false) {
299 if ($this->setting->get_level() == backup_setting::SECTION_LEVEL) {
300 $this->label = get_string('includesection', 'backup', $task->get_name());
301 } else if ($this->setting->get_level() == backup_setting::ACTIVITY_LEVEL) {
302 $this->label = $task->get_name();
305 return $this->label;
309 * Returns true if the setting is changeable.
311 * A setting is changeable if it meets either of the two following conditions.
313 * 1. The setting is not locked
314 * 2. The setting is locked but only by settings that are of the same level (same page)
316 * Condition 2 is really why we have this function
317 * @param int $level Optional, if provided only depedency_settings below or equal to this level are considered,
318 * when checking if the ui_setting is changeable. Although dependencies might cause a lock on this setting,
319 * they could be changeable in the same view.
320 * @return bool
322 public function is_changeable($level = null) {
323 if ($this->setting->get_status() === backup_setting::NOT_LOCKED) {
324 // Its not locked so its chanegable.
325 return true;
326 } else if ($this->setting->get_status() !== backup_setting::LOCKED_BY_HIERARCHY) {
327 // Its not changeable because its locked by permission or config.
328 return false;
329 } else if ($this->setting->has_dependencies_on_settings()) {
330 foreach ($this->setting->get_settings_depended_on() as $dependency) {
331 if ($level && $dependency->get_setting()->get_level() >= $level) {
332 continue;
334 if ($dependency->is_locked() && $dependency->get_setting()->get_level() !== $this->setting->get_level()) {
335 // Its not changeable because one or more dependancies arn't changeable.
336 return false;
339 // Its changeable because all dependencies are changeable.
340 return true;
342 // We should never get here but if we do return false to be safe.
343 // The setting would need to be locked by hierarchy and not have any deps.
344 return false;
350 * A text input user interface element for backup settings
352 * @package core_backup
353 * @copyright 2010 Sam Hemelryk
354 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
356 class backup_setting_ui_text extends backup_setting_ui {
358 * @var int
360 protected $type = backup_setting::UI_HTML_TEXTFIELD;
363 * Returns an array of properties suitable for generating a quickforms element
364 * @param base_task $task
365 * @param renderer_base $output
366 * @return array (element, name, label, attributes)
368 public function get_element_properties(base_task $task = null, renderer_base $output = null) {
369 $icon = $this->get_icon();
370 $context = context_course::instance($task->get_courseid());
371 $label = format_string($this->get_label($task), true, array('context' => $context));
372 if (!empty($icon)) {
373 $label .= $output->render($icon);
375 // Name, label, attributes.
376 return $this->apply_options(array(
377 'element' => 'text',
378 'name' => self::NAME_PREFIX.$this->name,
379 'label' => $label,
380 'attributes' => $this->attributes)
387 * A checkbox user interface element for backup settings (default)
389 * @package core_backup
390 * @copyright 2010 Sam Hemelryk
391 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
393 class backup_setting_ui_checkbox extends backup_setting_ui {
396 * @var int
398 protected $type = backup_setting::UI_HTML_CHECKBOX;
401 * @var bool
403 protected $changeable = true;
406 * The text to show next to the checkbox
407 * @var string
409 protected $text;
412 * Overridden constructor so we can take text argument
414 * @param backup_setting $setting
415 * @param string $label
416 * @param string $text
417 * @param array $attributes
418 * @param array $options
420 public function __construct(backup_setting $setting, $label = null, $text = null, array $attributes = array(), array $options = array()) {
421 parent::__construct($setting, $label, $attributes, $options);
422 $this->text = $text;
426 * Returns an array of properties suitable for generating a quickforms element
427 * @param base_task $task
428 * @param renderer_base $output
429 * @return array (element, name, label, text, attributes);
431 public function get_element_properties(base_task $task = null, renderer_base $output = null) {
432 // Name, label, text, attributes.
433 $icon = $this->get_icon();
434 $context = context_course::instance($task->get_courseid());
435 $label = format_string($this->get_label($task), true, array('context' => $context));
436 if (!empty($icon)) {
437 $label .= $output->render($icon);
439 return $this->apply_options(array(
440 'element' => 'checkbox',
441 'name' => self::NAME_PREFIX.$this->name,
442 'label' => $label,
443 'text' => $this->text,
444 'attributes' => $this->attributes
449 * Sets the text for the element
450 * @param string $text
452 public function set_text($text) {
453 $this->text = $text;
457 * Gets the static value for the element
458 * @global core_renderer $OUTPUT
459 * @return string
461 public function get_static_value() {
462 global $OUTPUT;
463 // Checkboxes are always yes or no.
464 if ($this->get_value()) {
465 return $OUTPUT->pix_icon('i/valid', get_string('yes'));
466 } else {
467 return $OUTPUT->pix_icon('i/invalid', get_string('no'));
472 * Returns true if the setting is changeable
473 * @param int $level Optional, if provided only depedency_settings below or equal to this level are considered,
474 * when checking if the ui_setting is changeable. Although dependencies might cause a lock on this setting,
475 * they could be changeable in the same view.
476 * @return bool
478 public function is_changeable($level = null) {
479 if ($this->changeable === false) {
480 return false;
481 } else {
482 return parent::is_changeable($level);
487 * Sets whether the setting is changeable,
488 * Note dependencies can still mark this setting changeable or not
489 * @param bool $newvalue
491 public function set_changeable($newvalue) {
492 $this->changeable = ($newvalue);
497 * Radio button user interface element for backup settings
499 * @package core_backup
500 * @copyright 2010 Sam Hemelryk
501 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
503 class backup_setting_ui_radio extends backup_setting_ui {
505 * @var int
507 protected $type = backup_setting::UI_HTML_RADIOBUTTON;
510 * The string shown next to the input
511 * @var string
513 protected $text;
516 * The value for the radio input
517 * @var string
519 protected $value;
522 * Constructor
524 * @param backup_setting $setting
525 * @param string $label
526 * @param string $text
527 * @param string $value
528 * @param array $attributes
529 * @param array $options
531 public function __construct(backup_setting $setting, $label = null, $text = null, $value = null, array $attributes = array(), array $options = array()) {
532 parent::__construct($setting, $label, $attributes, $options);
533 $this->text = $text;
534 $this->value = (string)$value;
538 * Returns an array of properties suitable for generating a quickforms element
539 * @param base_task $task
540 * @param renderer_base $output
541 * @return array (element, name, label, text, value, attributes)
543 public function get_element_properties(base_task $task = null, renderer_base $output = null) {
544 $icon = $this->get_icon();
545 $context = context_course::instance($task->get_courseid());
546 $label = format_string($this->get_label($task), true, array('context' => $context));
547 if (!empty($icon)) {
548 $label .= $output->render($icon);
550 // Name, label, text, value, attributes.
551 return $this->apply_options(array(
552 'element' => 'radio',
553 'name' => self::NAME_PREFIX.$this->name,
554 'label' => $label,
555 'text' => $this->text,
556 'value' => $this->value,
557 'attributes' => $this->attributes
561 * Sets the text next to this input
562 * @param text $text
564 public function set_text($text) {
565 $this->text = $text;
568 * Sets the value for the input
569 * @param string $value
571 public function set_value($value) {
572 $this->value = (string)$value;
575 * Gets the static value to show for the element
577 public function get_static_value() {
578 return $this->value;
583 * A select box, drop down user interface for backup settings
585 * @package core_backup
586 * @copyright 2010 Sam Hemelryk
587 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
589 class backup_setting_ui_select extends backup_setting_ui {
591 * @var int
593 protected $type = backup_setting::UI_HTML_DROPDOWN;
596 * An array of options to display in the select
597 * @var array
599 protected $values;
602 * Constructor
604 * @param backup_setting $setting
605 * @param string $label
606 * @param array $values
607 * @param array $attributes
608 * @param array $options
610 public function __construct(backup_setting $setting, $label = null, $values = null, array $attributes = array(), array $options = array()) {
611 parent::__construct($setting, $label, $attributes, $options);
612 $this->values = $values;
616 * Returns an array of properties suitable for generating a quickforms element
617 * @param base_task $task
618 * @param renderer_base $output
619 * @return array (element, name, label, options, attributes)
621 public function get_element_properties(base_task $task = null, renderer_base $output = null) {
622 $icon = $this->get_icon();
623 $context = context_course::instance($task->get_courseid());
624 $label = format_string($this->get_label($task), true, array('context' => $context));
625 if (!empty($icon)) {
626 $label .= $output->render($icon);
628 // Name, label, options, attributes.
629 return $this->apply_options(array(
630 'element' => 'select',
631 'name' => self::NAME_PREFIX.$this->name,
632 'label' => $label,
633 'options' => $this->values,
634 'attributes' => $this->attributes
639 * Sets the options for the select box
640 * @param array $values Associative array of value => text options
642 public function set_values(array $values) {
643 $this->values = $values;
647 * Gets the static value for this select element
648 * @return string
650 public function get_static_value() {
651 return $this->values[$this->get_value()];
655 * Returns true if the setting is changeable, false otherwise
657 * @param int $level Optional, if provided only depedency_settings below or equal to this level are considered,
658 * when checking if the ui_setting is changeable. Although dependencies might cause a lock on this setting,
659 * they could be changeable in the same view.
660 * @return bool
662 public function is_changeable($level = null) {
663 if (count($this->values) == 1) {
664 return false;
665 } else {
666 return parent::is_changeable($level);
671 * Returns the list of available values
672 * @return array
674 public function get_values() {
675 return $this->values;
680 * A date selector user interface widget for backup settings.
682 * @package core_backup
683 * @copyright 2010 Sam Hemelryk
684 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
686 class backup_setting_ui_dateselector extends backup_setting_ui_text {
689 * Returns an array of properties suitable for generating a quickforms element
690 * @param base_task $task
691 * @param renderer_base $output
692 * @return array (element, name, label, options, attributes)
694 public function get_element_properties(base_task $task = null, renderer_base $output = null) {
695 if (!array_key_exists('optional', $this->attributes)) {
696 $this->attributes['optional'] = false;
698 $properties = parent::get_element_properties($task, $output);
699 $properties['element'] = 'date_selector';
700 return $properties;
704 * Gets the static value for this select element
705 * @return string
707 public function get_static_value() {
708 $value = $this->get_value();
709 if (!empty($value)) {
710 return userdate($value);
712 return parent::get_static_value();
717 * A wrapper for defaultcustom form element - can have either text or date_selector type
719 * @package core_backup
720 * @copyright 2017 Marina Glancy
721 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
723 class backup_setting_ui_defaultcustom extends backup_setting_ui_text {
726 * Constructor
728 * @param backup_setting $setting
729 * @param string $label The label to display with the setting ui
730 * @param array $attributes Array of HTML attributes to apply to the element
731 * @param array $options Array of options to apply to the setting ui object
733 public function __construct(backup_setting $setting, $label = null, array $attributes = null, array $options = null) {
734 if (!is_array($attributes)) {
735 $attributes = [];
737 $attributes += ['customlabel' => get_string('overwrite', 'backup'),
738 'type' => 'text'];
739 parent::__construct($setting, $label, $attributes, $options);
743 * Returns an array of properties suitable for generating a quickforms element
744 * @param base_task $task
745 * @param renderer_base $output
746 * @return array (element, name, label, options, attributes)
748 public function get_element_properties(base_task $task = null, renderer_base $output = null) {
749 return ['element' => 'defaultcustom'] + parent::get_element_properties($task, $output);
753 * Gets the static value for this select element
754 * @return string
756 public function get_static_value() {
757 $value = $this->get_value();
758 if ($value === false) {
759 $value = $this->attributes['defaultvalue'];
761 if (!empty($value)) {
762 if ($this->attributes['type'] === 'date_selector' ||
763 $this->attributes['type'] === 'date_time_selector') {
764 return userdate($value);
767 return $value;
772 * Base setting UI exception class.
774 * @package core_backup
775 * @copyright 2010 Sam Hemelryk
776 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
778 class base_setting_ui_exception extends base_setting_exception {}
781 * Backup setting UI exception class.
783 * @package core_backup
784 * @copyright 2010 Sam Hemelryk
785 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
787 class backup_setting_ui_exception extends base_setting_ui_exception {};