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. 13 // 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/>. 16 17 declare(strict_types=1); 18 19 namespace core\output; 20 21 use renderer_base; 22 23 /** 24 * A single-select combobox widget that is functionally similar to an HTML select element. 25 * 26 * @package core 27 * @category output 28 * @copyright 2022 Shamim Rezaie <shamim@moodle.com> 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 */ 31 class select_menu implements \renderable, \templatable { 32 /** @var array List of options. */ 33 protected $options; 34 35 /** @var string|null The value of the preselected option. */ 36 protected $selected; 37 38 /** @var string The combobox label */ 39 protected $label; 40 41 /** @var array Button label's attributes */ 42 protected $labelattributes = []; 43 44 /** @var string Name of the combobox element */ 45 protected $name; 46 47 /** 48 * select_menu constructor. 49 * 50 * @param string $name Name of the combobox element 51 * @param array $options List of options in an associative array format like ['val' => 'Option']. 52 * Supports grouped options as well. 53 * @param string|null $selected The value of the preselected option. 54 */ 55 public function __construct(string $name, array $options, string $selected = null) { 56 $this->name = $name; 57 $this->options = $options; 58 $this->selected = $selected; 59 } 60 61 /** 62 * Sets the select menu's label. 63 * 64 * @param string $label The label. 65 * @param array $attributes List of attributes to apply on the label element. 66 */ 67 public function set_label(string $label, array $attributes = []) { 68 $this->label = $label; 69 $this->labelattributes = $attributes; 70 } 71 72 /** 73 * Flatten the options for Mustache. 74 * 75 * @return array 76 */ 77 protected function flatten_options(): array { 78 $flattened = []; 79 80 foreach ($this->options as $value => $option) { 81 if (is_array($option)) { 82 foreach ($option as $groupname => $optoptions) { 83 if (!isset($flattened[$groupname])) { 84 $flattened[$groupname] = [ 85 'name' => $groupname, 86 'isgroup' => true, 87 'id' => \html_writer::random_id('select-menu-group'), 88 'options' => [] 89 ]; 90 } 91 foreach ($optoptions as $optvalue => $optoption) { 92 $flattened[$groupname]['options'][$optvalue] = [ 93 'name' => $optoption, 94 'value' => $optvalue, 95 'selected' => $this->selected == $optvalue, 96 'id' => \html_writer::random_id('select-menu-option'), 97 ]; 98 } 99 } 100 } else { 101 $flattened[$value] = [ 102 'name' => $option, 103 'value' => $value, 104 'selected' => $this->selected == $value, 105 'id' => \html_writer::random_id('select-menu-option'), 106 ]; 107 } 108 } 109 110 // Make non-associative array. 111 foreach ($flattened as $key => $value) { 112 if (!empty($value['options'])) { 113 $flattened[$key]['options'] = array_values($value['options']); 114 } 115 } 116 $flattened = array_values($flattened); 117 118 return $flattened; 119 } 120 121 /** 122 * Return the name of the selected option. 123 * 124 * @return string|null The name of the selected option or null. 125 */ 126 private function get_selected_option(): ?string { 127 foreach ($this->options as $value => $option) { 128 if (is_array($option)) { // This is a group. 129 foreach ($option as $groupname => $optoptions) { 130 // Loop through the options within the group to check whether any of them matches the 'selected' value. 131 foreach ($optoptions as $optvalue => $optoption) { 132 // If the value of the option matches the 'selected' value, return the name of the option. 133 if ($this->selected == $optvalue) { 134 return $optoption; 135 } 136 } 137 } 138 } else { // This is a standard option item. 139 // If the value of the option matches the 'selected' value, return the name of the option. 140 if ($this->selected == $value) { 141 return $option; 142 } 143 } 144 } 145 return null; 146 } 147 148 /** 149 * Export for template. 150 * 151 * @param renderer_base $output The renderer. 152 * @return \stdClass 153 */ 154 public function export_for_template(renderer_base $output): \stdClass { 155 $data = new \stdClass(); 156 $data->baseid = \html_writer::random_id('select-menu'); 157 $data->label = $this->label; 158 $data->options = $this->flatten_options(); 159 $data->selectedoption = $this->get_selected_option(); 160 $data->name = $this->name; 161 $data->value = $this->selected; 162 163 // Label attributes. 164 $data->labelattributes = []; 165 // Map the label attributes. 166 foreach ($this->labelattributes as $key => $value) { 167 $data->labelattributes[] = ['name' => $key, 'value' => $value]; 168 } 169 170 return $data; 171 } 172 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body