MDL-80248 course: Deprecate get/set_section_number()
[moodle.git] / course / format / classes / output / local / content / cm.php
blob03473e531447d7748bf7a3a207f3bc77fe12f992
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 * Contains the default activity list from a section.
20 * @package core_courseformat
21 * @copyright 2020 Ferran Recio <ferran@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 namespace core_courseformat\output\local\content;
27 use cm_info;
28 use context_course;
29 use core\output\named_templatable;
30 use core_availability\info_module;
31 use core_courseformat\base as course_format;
32 use core_courseformat\output\local\courseformat_named_templatable;
33 use renderable;
34 use renderer_base;
35 use section_info;
36 use stdClass;
38 /**
39 * Base class to render a course module inside a course format.
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
45 class cm implements named_templatable, renderable {
46 use courseformat_named_templatable;
48 /** @var course_format the course format */
49 protected $format;
51 /** @var section_info the section object */
52 private $section;
54 /** @var cm_info the course module instance */
55 protected $mod;
57 /** @var array optional display options */
58 protected $displayoptions;
60 /** @var string the activity name output class name */
61 protected $cmnameclass;
63 /** @var string the activity control menu class name */
64 protected $controlmenuclass;
66 /** @var string the activity availability class name */
67 protected $availabilityclass;
69 /** @var string the activity completion class name */
70 protected $completionclass;
72 /** @var string the activity visibility class name */
73 protected $visibilityclass;
75 /** @var string the activity groupmode badge class name */
76 protected $groupmodeclass;
78 /**
79 * Constructor.
81 * @param course_format $format the course format
82 * @param section_info $section the section info
83 * @param cm_info $mod the course module ionfo
84 * @param array $displayoptions optional extra display options
86 public function __construct(course_format $format, section_info $section, cm_info $mod, array $displayoptions = []) {
87 $this->format = $format;
88 $this->section = $section;
89 $this->mod = $mod;
91 // Add extra display options.
92 $this->displayoptions = $displayoptions;
93 $this->load_classes();
95 // Get the necessary classes.
96 $this->cmnameclass = $format->get_output_classname('content\\cm\\cmname');
97 $this->controlmenuclass = $format->get_output_classname('content\\cm\\controlmenu');
98 $this->availabilityclass = $format->get_output_classname('content\\cm\\availability');
99 $this->completionclass = $format->get_output_classname('content\\cm\\completion');
100 $this->visibilityclass = $format->get_output_classname('content\\cm\\visibility');
101 $this->groupmodeclass = $format->get_output_classname('content\\cm\\groupmode');
105 * Export this data so it can be used as the context for a mustache template.
107 * @param renderer_base $output typically, the renderer that's calling this function
108 * @return stdClass data context for a mustache template
110 public function export_for_template(renderer_base $output): stdClass {
111 global $PAGE;
113 $mod = $this->mod;
114 $displayoptions = $this->displayoptions;
116 $data = (object)[
117 'grouping' => $mod->get_grouping_label($displayoptions['textclasses']),
118 'modname' => get_string('pluginname', 'mod_' . $mod->modname),
119 'url' => $mod->url,
120 'activityname' => $mod->get_formatted_name(),
121 'textclasses' => $displayoptions['textclasses'],
122 'classlist' => [],
123 'cmid' => $mod->id,
124 'editing' => $PAGE->user_is_editing(),
127 // Add partial data segments.
128 $haspartials = [];
129 $haspartials['cmname'] = $this->add_cm_name_data($data, $output);
130 $haspartials['availability'] = $this->add_availability_data($data, $output);
131 $haspartials['alternative'] = $this->add_alternative_content_data($data, $output);
132 $haspartials['completion'] = $this->add_completion_data($data, $output);
133 $haspartials['dates'] = $this->add_dates_data($data, $output);
134 $haspartials['editor'] = $this->add_editor_data($data, $output);
135 $haspartials['groupmode'] = $this->add_groupmode_data($data, $output);
136 $haspartials['visibility'] = $this->add_visibility_data($data, $output);
137 $this->add_format_data($data, $haspartials, $output);
139 // Calculated fields.
140 if (!empty($data->url)) {
141 $data->hasurl = true;
143 return $data;
147 * Add course module name attributes to the data structure.
149 * @param stdClass $data the current cm data reference
150 * @param renderer_base $output typically, the renderer that's calling this function
151 * @return bool if the cm has name data
153 protected function add_cm_name_data(stdClass &$data, renderer_base $output): bool {
154 // Mod inplace name editable.
155 $cmname = new $this->cmnameclass(
156 $this->format,
157 $this->section,
158 $this->mod,
159 null,
160 $this->displayoptions
162 $data->cmname = $cmname->export_for_template($output);
163 $data->hasname = $cmname->has_name();
164 return $data->hasname;
168 * Add the module availability to the data structure.
170 * @param stdClass $data the current cm data reference
171 * @param renderer_base $output typically, the renderer that's calling this function
172 * @return bool if the cm has mod availability
174 protected function add_availability_data(stdClass &$data, renderer_base $output): bool {
175 if (!$this->mod->visible) {
176 $data->modavailability = null;
177 return false;
179 // Mod availability output class.
180 $availability = new $this->availabilityclass(
181 $this->format,
182 $this->section,
183 $this->mod,
184 $this->displayoptions
186 $modavailability = $availability->export_for_template($output);
187 $data->modavailability = $modavailability;
188 return $availability->has_availability($output);
192 * Add the alternative content to the data structure.
194 * @param stdClass $data the current cm data reference
195 * @param renderer_base $output typically, the renderer that's calling this function
196 * @return bool if the cm has alternative content
198 protected function add_alternative_content_data(stdClass &$data, renderer_base $output): bool {
199 $altcontent = $this->mod->get_formatted_content(
200 ['overflowdiv' => true, 'noclean' => true]
202 $data->altcontent = (empty($altcontent)) ? false : $altcontent;
203 $data->afterlink = $this->mod->afterlink;
205 $activitybadgedata = $this->mod->get_activitybadge($output);
206 if (!empty($activitybadgedata)) {
207 $data->activitybadge = $activitybadgedata;
210 return !empty($data->altcontent);
214 * Add activity dates information to the data structure.
216 * @param stdClass $data the current cm data reference
217 * @param renderer_base $output typically, the renderer that's calling this function
218 * @return bool the module has completion information
220 protected function add_dates_data(stdClass &$data, renderer_base $output): bool {
221 global $USER;
222 $course = $this->mod->get_course();
223 if (!$course->showactivitydates) {
224 return false;
226 $activitydates = \core\activity_dates::get_dates_for_module($this->mod, $USER->id);
227 $templatedata = new \core_course\output\activity_dates($activitydates);
228 $data->dates = $templatedata->export_for_template($output);
230 return $data->dates->hasdates;
234 * Add activity completion information to the data structure.
236 * @param stdClass $data the current cm data reference
237 * @param renderer_base $output typically, the renderer that's calling this function
238 * @return bool the module has completion information
240 protected function add_completion_data(stdClass &$data, renderer_base $output): bool {
241 $completion = new $this->completionclass($this->format, $this->section, $this->mod);
242 $templatedata = $completion->export_for_template($output);
243 if ($templatedata) {
244 $data->completion = $templatedata;
245 return true;
247 return false;
251 * Add activity information to the data structure.
253 * @param stdClass $data the current cm data reference
254 * @param bool[] $haspartials the result of loading partial data elements
255 * @param renderer_base $output typically, the renderer that's calling this function
256 * @return bool if the cm has format data
258 protected function add_format_data(stdClass &$data, array $haspartials, renderer_base $output): bool {
259 $result = false;
260 // Legacy indentation.
261 if (!empty($this->mod->indent) && $this->format->uses_indentation()) {
262 $data->indent = $this->mod->indent;
263 if ($this->mod->indent > 15) {
264 $data->hugeindent = true;
265 $result = true;
268 // Stealth and hidden from student.
269 if (!$this->mod->visible) {
270 // This module is hidden but current user has capability to see it.
271 $data->modhiddenfromstudents = true;
272 $result = true;
273 } else if ($this->mod->is_stealth()) {
274 // This module is available but is normally not displayed on the course page
275 // (this user can see it because they can manage it).
276 $data->modstealth = true;
277 $result = true;
279 // Special inline activity format.
280 if (
281 $this->mod->has_custom_cmlist_item() &&
282 !$haspartials['availability'] &&
283 !$haspartials['completion'] &&
284 !$haspartials['dates'] &&
285 !$haspartials['groupmode'] &&
286 !isset($data->modhiddenfromstudents) &&
287 !isset($data->modstealth) &&
288 !$this->format->show_editor()
290 $data->modinline = true;
291 $result = true;
293 return $result;
297 * Add course editor attributes to the data structure.
299 * @param stdClass $data the current cm data reference
300 * @param renderer_base $output typically, the renderer that's calling this function
301 * @return bool if the cm has editor data
303 protected function add_editor_data(stdClass &$data, renderer_base $output): bool {
304 $course = $this->format->get_course();
305 $coursecontext = context_course::instance($course->id);
306 $editcaps = [];
307 if (has_capability('moodle/course:activityvisibility', $coursecontext)) {
308 $editcaps = ['moodle/course:activityvisibility'];
310 if (!$this->format->show_editor($editcaps)) {
311 return false;
313 $returnsection = $this->format->get_sectionnum();
314 // Edit actions.
315 $controlmenu = new $this->controlmenuclass(
316 $this->format,
317 $this->section,
318 $this->mod,
319 $this->displayoptions
321 $data->controlmenu = $controlmenu->export_for_template($output);
322 if (!$this->format->supports_components()) {
323 // Add the legacy YUI move link.
324 $data->moveicon = course_get_cm_move($this->mod, $returnsection);
326 return true;
330 * Add group mode information to the data structure.
332 * @param stdClass $data the current cm data reference
333 * @param renderer_base $output typically, the renderer that's calling this function
334 * @return bool the module has group mode information
336 protected function add_groupmode_data(stdClass &$data, renderer_base $output): bool {
337 $groupmode = new $this->groupmodeclass($this->format, $this->section, $this->mod);
338 $data->groupmodeinfo = $groupmode->export_for_template($output);
339 return !empty($data->groupmodeinfo);
343 * Add visibility information to the data structure.
345 * @param stdClass $data the current cm data reference
346 * @param renderer_base $output typically, the renderer that's calling this function
347 * @return bool if the cm has visibility data
349 protected function add_visibility_data(stdClass &$data, renderer_base $output): bool {
350 $visibility = new $this->visibilityclass($this->format, $this->section, $this->mod);
351 $templatedata = $visibility->export_for_template($output);
352 if ($templatedata) {
353 $data->visibility = $templatedata;
354 return true;
356 return false;
360 * Returns the CSS classes for the activity name/content
363 protected function load_classes() {
364 $mod = $this->mod;
366 $linkclasses = '';
367 $textclasses = '';
368 if ($mod->uservisible) {
369 $info = new info_module($mod);
370 $conditionalhidden = !$info->is_available_for_all();
371 $accessiblebutdim = (!$mod->visible || $conditionalhidden) &&
372 has_capability('moodle/course:viewhiddenactivities', $mod->context);
373 if ($accessiblebutdim && $conditionalhidden) {
374 $linkclasses .= ' conditionalhidden';
375 $textclasses .= ' conditionalhidden';
378 $this->displayoptions['linkclasses'] = $linkclasses;
379 $this->displayoptions['textclasses'] = $textclasses;
380 $this->displayoptions['onclick'] = htmlspecialchars_decode($mod->onclick, ENT_QUOTES);;
384 * Get the activity link classes.
386 * @return string the activity link classes.
388 public function get_link_classes(): string {
389 return $this->displayoptions['linkclasses'] ?? '';
393 * Get the activity text/description classes.
395 * @return string the activity text classes.
397 public function get_text_classes(): string {
398 return $this->displayoptions['textclasses'] ?? '';
402 * Get the activity onclick code.
404 * @return string the activity onclick.
406 public function get_onclick_code(): string {
407 return $this->displayoptions['onclick'];