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 /** 18 * Contains the default activity availability information. 19 * 20 * @package core_courseformat 21 * @copyright 2023 Ferran Recio <ferran@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_courseformat\output\local\content\cm; 26 27 use cm_info; 28 use core_courseformat\base as course_format; 29 use core_courseformat\output\local\courseformat_named_templatable; 30 use core\output\choicelist; 31 use core\output\local\dropdown\status; 32 use core\output\named_templatable; 33 use pix_icon; 34 use renderable; 35 use section_info; 36 use stdClass; 37 38 /** 39 * Base class to render a course module availability inside a course format. 40 * 41 * @package core_courseformat 42 * @copyright 2020 Ferran Recio <ferran@moodle.com> 43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 44 */ 45 class visibility implements named_templatable, renderable { 46 use courseformat_named_templatable; 47 48 /** @var course_format the course format */ 49 protected $format; 50 51 /** @var section_info the section object */ 52 protected $section; 53 54 /** @var cm_info the course module instance */ 55 protected $mod; 56 57 /** 58 * Constructor. 59 * @param course_format $format the course format 60 * @param section_info $section the section info 61 * @param cm_info $mod the course module ionfo 62 */ 63 public function __construct(course_format $format, section_info $section, cm_info $mod) { 64 $this->format = $format; 65 $this->section = $section; 66 $this->mod = $mod; 67 } 68 69 /** 70 * Export this data so it can be used as the context for a mustache template. 71 * 72 * @param \renderer_base $output typically, the renderer that's calling this function 73 * @return stdClass|null data context for a mustache template 74 */ 75 public function export_for_template(\renderer_base $output): ?stdClass { 76 if (!$this->show_visibility()) { 77 return null; 78 } 79 $format = $this->format; 80 // In rare legacy cases, the section could be stealth (orphaned) but they are not editable. 81 if (!$format->show_editor()) { 82 return $this->build_static_data($output); 83 } else { 84 return $this->build_editor_data($output); 85 } 86 } 87 88 /** 89 * Check if the visibility is displayed. 90 * @return bool 91 */ 92 protected function show_visibility(): bool { 93 return !$this->mod->visible || $this->mod->is_stealth(); 94 } 95 96 /** 97 * Get the icon for the section visibility. 98 * @param string $selected the visibility selected value 99 * @return pix_icon 100 */ 101 protected function get_icon(string $selected): pix_icon { 102 if ($selected === 'hide') { 103 return new pix_icon('t/show', ''); 104 } else if ($selected === 'stealth') { 105 return new pix_icon('t/stealth', ''); 106 } else { 107 return new pix_icon('t/hide', ''); 108 } 109 } 110 111 /** 112 * Build the data for the editor. 113 * @param \renderer_base $output typically, the renderer that's calling this function 114 * @return stdClass|null data context for a mustache template 115 */ 116 public function build_editor_data(\renderer_base $output): ?stdClass { 117 $choice = $this->get_choice_list(); 118 return $this->get_dropdown_data($output, $choice); 119 } 120 121 /** 122 * Build the data for the interactive dropdown. 123 * @param \renderer_base $output 124 * @param choicelist $choice the choice list 125 * @return stdClass 126 */ 127 protected function get_dropdown_data( 128 \renderer_base $output, 129 choicelist $choice, 130 ): stdClass { 131 $badgetext = $output->sr_text(get_string('availability')); 132 133 if (!$this->mod->visible) { 134 $badgetext .= get_string('hiddenfromstudents'); 135 $icon = $this->get_icon('hide'); 136 } else if ($this->mod->is_stealth()) { 137 $badgetext .= get_string('hiddenoncoursepage'); 138 $icon = $this->get_icon('stealth'); 139 } else { 140 $badgetext .= get_string("availability_show", 'core_courseformat'); 141 $icon = $this->get_icon('show'); 142 } 143 $dropdown = new status( 144 $output->render($icon) . ' ' . $badgetext, 145 $choice, 146 ['dialogwidth' => status::WIDTH['big']], 147 ); 148 return (object) [ 149 'isInteractive' => true, 150 'dropwdown' => $dropdown->export_for_template($output), 151 ]; 152 } 153 154 /** 155 * Get the availability choice list. 156 * @return choicelist 157 */ 158 public function get_choice_list(): choicelist { 159 $choice = $this->create_choice_list(); 160 $choice->set_selected_value($this->get_selected_choice_value()); 161 return $choice; 162 } 163 164 /** 165 * Get the selected choice value depending on the course, section and stealth settings. 166 * @return string 167 */ 168 protected function get_selected_choice_value(): string { 169 if (!$this->mod->visible) { 170 return 'hide'; 171 } 172 if (!$this->mod->is_stealth()) { 173 return 'show'; 174 } 175 if (!$this->section->visible) { 176 // All visible activities in a hidden sections are considered stealth 177 // but they don't use the stealth attribute for it. It is just implicit. 178 return 'show'; 179 } 180 return 'stealth'; 181 } 182 183 /** 184 * Create a choice list for the dropdown. 185 * @return choicelist the choice list 186 */ 187 protected function create_choice_list(): choicelist { 188 global $CFG; 189 190 $choice = new choicelist(); 191 if ($this->section->visible || $this->mod->has_view()) { 192 $label = $this->section->visible ? 'show' : 'stealth'; 193 $choice->add_option( 194 'show', 195 get_string("availability_{$label}", 'core_courseformat'), 196 $this->get_option_data($label, 'cmShow') 197 ); 198 } 199 $choice->add_option( 200 'hide', 201 get_string('availability_hide', 'core_courseformat'), 202 $this->get_option_data('hide', 'cmHide') 203 ); 204 205 if ($CFG->allowstealth && $this->format->allow_stealth_module_visibility($this->mod, $this->section)) { 206 $choice->add_option( 207 'stealth', 208 get_string('availability_stealth', 'core_courseformat'), 209 $this->get_option_data('stealth', 'cmStealth') 210 ); 211 } 212 return $choice; 213 } 214 215 /** 216 * Get the data for the option. 217 * @param string $name the name of the option 218 * @param string $action the state action of the option 219 * @return array 220 */ 221 private function get_option_data(string $name, string $action): array { 222 return [ 223 'description' => get_string("availability_{$name}_help", 'core_courseformat'), 224 'icon' => $this->get_icon($name), 225 // Non-ajax behat is not smart enough to discrimante hidden links 226 // so we need to keep providing the non-ajax links. 227 'url' => $this->format->get_non_ajax_cm_action_url($action, $this->mod), 228 'extras' => [ 229 'data-id' => $this->mod->id, 230 'data-action' => $action, 231 ] 232 ]; 233 } 234 235 /** 236 * Build the static badges data. 237 * @param \renderer_base $output typically, the renderer that's calling this function 238 * @return stdClass|null data context for a mustache template 239 */ 240 public function build_static_data(\renderer_base $output): ?stdClass { 241 $data = (object) [ 242 'isInteractive' => false, 243 ]; 244 245 if (!$this->mod->visible) { 246 $data->modhiddenfromstudents = true; 247 } else if ($this->mod->is_stealth()) { 248 $data->modstealth = true; 249 } 250 return $data; 251 } 252 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body