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 * File containing the class activity information renderable. 19 * 20 * @package core_course 21 * @copyright 2021 Jun Pataleta <jun@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24namespace core_course\output; 25 26defined('MOODLE_INTERNAL') || die(); 27 28use cm_info; 29use completion_info; 30use context; 31use core\activity_dates; 32use core_availability\info; 33use core_completion\cm_completion_details; 34use core_user; 35use core_user\fields; 36use renderable; 37use renderer_base; 38use stdClass; 39use templatable; 40 41/** 42 * The activity information renderable class. 43 * 44 * @package core_course 45 * @copyright 2021 Jun Pataleta <jun@moodle.com> 46 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 47 */ 48class activity_information implements renderable, templatable { 49 50 /** @var cm_info The course module information. */ 51 protected $cminfo = null; 52 53 /** @var array The array of relevant dates for this activity. */ 54 protected $activitydates = []; 55 56 /** @var cm_completion_details The user's completion details for this activity. */ 57 protected $cmcompletion = null; 58 59 /** 60 * Constructor. 61 * 62 * @param cm_info $cminfo The course module information. 63 * @param cm_completion_details $cmcompletion The course module information. 64 * @param array $activitydates The activity dates. 65 */ 66 public function __construct(cm_info $cminfo, cm_completion_details $cmcompletion, array $activitydates) { 67 $this->cminfo = $cminfo; 68 $this->cmcompletion = $cmcompletion; 69 $this->activitydates = $activitydates; 70 } 71 72 /** 73 * Export this data so it can be used as the context for a mustache template. 74 * 75 * @param renderer_base $output Renderer base. 76 * @return stdClass 77 */ 78 public function export_for_template(renderer_base $output): stdClass { 79 $data = $this->build_completion_data(); 80 81 $data->cmid = $this->cminfo->id; 82 $data->activityname = $this->cminfo->name; 83 $this->build_dates_data($data); 84 $data->hasdates = !empty($this->activitydates); 85 86 return $data; 87 } 88 89 /** 90 * Builds the dates data for export. 91 * 92 * @param stdClass $data 93 */ 94 protected function build_dates_data(stdClass $data): void { 95 foreach ($this->activitydates as $date) { 96 if (empty($date['relativeto'])) { 97 $date['datestring'] = userdate($date['timestamp'], get_string('strftimedaydatetime', 'core_langconfig')); 98 } else { 99 $diffstr = get_time_interval_string($date['timestamp'], $date['relativeto']); 100 if ($date['timestamp'] >= $date['relativeto']) { 101 $date['datestring'] = get_string('relativedatessubmissionduedateafter', 'core_course', 102 ['datediffstr' => $diffstr]); 103 } else { 104 $date['datestring'] = get_string('relativedatessubmissionduedatebefore', 'core_course', 105 ['datediffstr' => $diffstr]); 106 } 107 } 108 $data->activitydates[] = $date; 109 } 110 } 111 112 /** 113 * Builds the completion data for export. 114 * 115 * @return stdClass 116 */ 117 protected function build_completion_data(): stdClass { 118 global $CFG; 119 120 $data = new stdClass(); 121 122 $data->hascompletion = $this->cmcompletion->has_completion(); 123 $data->isautomatic = $this->cmcompletion->is_automatic(); 124 $data->showmanualcompletion = $this->cmcompletion->show_manual_completion(); 125 126 // Get the name of the user overriding the completion condition, if available. 127 $data->overrideby = null; 128 $overrideby = $this->cmcompletion->overridden_by(); 129 $overridebyname = null; 130 if (!empty($overrideby)) { 131 $userfields = fields::for_name(); 132 $overridebyrecord = core_user::get_user($overrideby, 'id ' . $userfields->get_sql()->selects, MUST_EXIST); 133 $data->overrideby = fullname($overridebyrecord); 134 } 135 136 // We'll show only the completion conditions and not the completion status if we're not tracking completion for this user 137 // (e.g. a teacher, admin). 138 $data->istrackeduser = $this->cmcompletion->is_tracked_user(); 139 140 // Overall completion states. 141 $overallcompletion = $this->cmcompletion->get_overall_completion(); 142 $data->overallcomplete = $overallcompletion == COMPLETION_COMPLETE; 143 $data->overallincomplete = $overallcompletion == COMPLETION_INCOMPLETE; 144 145 // Set an accessible description for manual completions with overridden completion state. 146 if (!$data->isautomatic && $data->overrideby) { 147 $setbydata = (object)[ 148 'activityname' => $this->cminfo->name, 149 'setby' => $data->overrideby, 150 ]; 151 $setbylangkey = $data->overallcomplete ? 'completion_setby:manual:done' : 'completion_setby:manual:markdone'; 152 $data->accessibledescription = get_string($setbylangkey, 'course', $setbydata); 153 } 154 155 // Whether the completion of this activity controls the availability of other activities/sections in the course. 156 $data->withavailability = false; 157 $course = $this->cminfo->get_course(); 158 // An activity with manual completion tracking which is used to enable access to other activities/sections in 159 // the course needs to refresh the page after having its completion state toggled. This withavailability flag will enable 160 // this functionality on the course homepage. Otherwise, the completion toggling will just happen normally via ajax. 161 if ($this->cmcompletion->has_completion() && !$this->cmcompletion->is_automatic()) { 162 $data->withavailability = !empty($CFG->enableavailability) && info::completion_value_used($course, $this->cminfo->id); 163 } 164 165 // Whether this activity is visible to the user. If not, completion information will not be shown. 166 $data->uservisible = $this->cminfo->uservisible; 167 168 // Build automatic completion details. 169 $details = []; 170 foreach ($this->cmcompletion->get_details() as $key => $detail) { 171 // Set additional attributes for the template. 172 $detail->key = $key; 173 $detail->statuscomplete = in_array($detail->status, [COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS]); 174 $detail->statuscompletefail = $detail->status == COMPLETION_COMPLETE_FAIL; 175 $detail->statusincomplete = $detail->status == COMPLETION_INCOMPLETE; 176 177 // Add an accessible description to be used for title and aria-label attributes for overridden completion details. 178 if ($data->overrideby) { 179 $setbydata = (object)[ 180 'condition' => $detail->description, 181 'setby' => $data->overrideby, 182 ]; 183 $overridestatus = $detail->statuscomplete ? 'done' : 'todo'; 184 $detail->accessibledescription = get_string('completion_setby:auto:' . $overridestatus, 'course', $setbydata); 185 } 186 187 // We don't need the status in the template. 188 unset($detail->status); 189 190 $details[] = $detail; 191 } 192 $data->completiondetails = $details; 193 194 return $data; 195 } 196} 197