2 // This file is part of Moodle - http://moodle.org/
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.
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/>.
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
;
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
;
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 */
51 /** @var section_info the section object */
54 /** @var cm_info the course module instance */
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;
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;
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
{
114 $displayoptions = $this->displayoptions
;
117 'grouping' => $mod->get_grouping_label($displayoptions['textclasses']),
118 'modname' => get_string('pluginname', 'mod_' . $mod->modname
),
120 'activityname' => $mod->get_formatted_name(),
121 'textclasses' => $displayoptions['textclasses'],
124 'editing' => $PAGE->user_is_editing(),
127 // Add partial data segments.
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;
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(
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;
179 // Mod availability output class.
180 $availability = new $this->availabilityclass(
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 {
222 $course = $this->mod
->get_course();
223 if (!$course->showactivitydates
) {
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);
244 $data->completion
= $templatedata;
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 {
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;
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;
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;
279 // Special inline activity format.
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;
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
);
307 if (has_capability('moodle/course:activityvisibility', $coursecontext)) {
308 $editcaps = ['moodle/course:activityvisibility'];
310 if (!$this->format
->show_editor($editcaps)) {
313 $returnsection = $this->format
->get_sectionnum();
315 $controlmenu = new $this->controlmenuclass(
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);
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);
353 $data->visibility
= $templatedata;
360 * Returns the CSS classes for the activity name/content
363 protected function load_classes() {
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'];