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 * Display user completion report 19 * 20 * @package report 21 * @subpackage completion 22 * @copyright 2009 Catalyst IT Ltd 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26require('../../config.php'); 27require_once($CFG->dirroot.'/report/completion/lib.php'); 28require_once($CFG->libdir.'/completionlib.php'); 29 30$userid = required_param('id', PARAM_INT); 31$courseid = required_param('course', PARAM_INT); 32 33$user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0), '*', MUST_EXIST); 34$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST); 35 36$coursecontext = context_course::instance($course->id); 37$personalcontext = context_user::instance($user->id); 38 39if ($USER->id != $user->id and has_capability('moodle/user:viewuseractivitiesreport', $personalcontext) 40 and !is_enrolled($coursecontext, $USER) and is_enrolled($coursecontext, $user)) { 41 //TODO: do not require parents to be enrolled in courses - this is a hack! 42 require_login(); 43 $PAGE->set_course($course); 44} else { 45 require_login($course); 46} 47 48if (!report_completion_can_access_user_report($user, $course)) { 49 // this should never happen 50 print_error('nocapability', 'report_completion'); 51} 52 53$stractivityreport = get_string('activityreport'); 54 55$PAGE->set_pagelayout('admin'); 56$PAGE->set_url('/report/completion/user.php', array('id'=>$user->id, 'course'=>$course->id)); 57$PAGE->navigation->extend_for_user($user); 58$PAGE->navigation->set_userid_for_parent_checks($user->id); // see MDL-25805 for reasons and for full commit reference for reversal when fixed. 59$PAGE->set_title("$course->shortname: $stractivityreport"); 60$PAGE->set_heading($course->fullname); 61echo $OUTPUT->header(); 62 63 64// Display course completion user report 65 66// Grab all courses the user is enrolled in and their completion status 67$sql = " 68 SELECT DISTINCT 69 c.id AS id 70 FROM 71 {course} c 72 INNER JOIN 73 {context} con 74 ON con.instanceid = c.id 75 INNER JOIN 76 {role_assignments} ra 77 ON ra.contextid = con.id 78 INNER JOIN 79 {enrol} e 80 ON c.id = e.courseid 81 INNER JOIN 82 {user_enrolments} ue 83 ON e.id = ue.enrolid AND ra.userid = ue.userid 84 AND ra.userid = {$user->id} 85"; 86 87// Get roles that are tracked by course completion 88if ($roles = $CFG->gradebookroles) { 89 $sql .= ' 90 AND ra.roleid IN ('.$roles.') 91 '; 92} 93 94$sql .= ' 95 WHERE 96 con.contextlevel = '.CONTEXT_COURSE.' 97 AND c.enablecompletion = 1 98'; 99 100 101// If we are looking at a specific course 102if ($course->id != 1) { 103 $sql .= ' 104 AND c.id = '.(int)$course->id.' 105 '; 106} 107 108// Check if result is empty 109$rs = $DB->get_recordset_sql($sql); 110if (!$rs->valid()) { 111 112 if ($course->id != 1) { 113 $error = get_string('nocompletions', 'report_completion'); // TODO: missing string 114 } else { 115 $error = get_string('nocompletioncoursesenroled', 'report_completion'); // TODO: missing string 116 } 117 118 echo $OUTPUT->notification($error); 119 $rs->close(); // not going to loop (but break), close rs 120 echo $OUTPUT->footer(); 121 die(); 122} 123 124// Categorize courses by their status 125$courses = array( 126 'inprogress' => array(), 127 'complete' => array(), 128 'unstarted' => array() 129); 130 131// Sort courses by the user's status in each 132foreach ($rs as $course_completion) { 133 $c_info = new completion_info((object)$course_completion); 134 135 // Is course complete? 136 $coursecomplete = $c_info->is_course_complete($user->id); 137 138 // Has this user completed any criteria? 139 $criteriacomplete = $c_info->count_course_user_data($user->id); 140 141 if ($coursecomplete) { 142 $courses['complete'][] = $c_info; 143 } else if ($criteriacomplete) { 144 $courses['inprogress'][] = $c_info; 145 } else { 146 $courses['unstarted'][] = $c_info; 147 } 148} 149$rs->close(); // after loop, close rs 150 151// Loop through course status groups 152foreach ($courses as $type => $infos) { 153 154 // If there are courses with this status 155 if (!empty($infos)) { 156 157 echo '<h1 align="center">'.get_string($type, 'report_completion').'</h1>'; 158 echo '<table class="generaltable boxaligncenter">'; 159 echo '<tr class="ccheader">'; 160 echo '<th class="c0 header" scope="col">'.get_string('course').'</th>'; 161 echo '<th class="c1 header" scope="col">'.get_string('requiredcriteria', 'completion').'</th>'; 162 echo '<th class="c2 header" scope="col">'.get_string('status').'</th>'; 163 echo '<th class="c3 header" scope="col" width="15%">'.get_string('info').'</th>'; 164 165 if ($type === 'complete') { 166 echo '<th class="c4 header" scope="col">'.get_string('completiondate', 'report_completion').'</th>'; 167 } 168 169 echo '</tr>'; 170 171 // For each course 172 foreach ($infos as $c_info) { 173 174 // Get course info 175 $c_course = $DB->get_record('course', array('id' => $c_info->course_id)); 176 $course_context = context_course::instance($c_course->id, MUST_EXIST); 177 $course_name = format_string($c_course->fullname, true, array('context' => $course_context)); 178 179 // Get completions 180 $completions = $c_info->get_completions($user->id); 181 182 // Save row data 183 $rows = array(); 184 185 // For aggregating activity completion 186 $activities = array(); 187 $activities_complete = 0; 188 189 // For aggregating prerequisites 190 $prerequisites = array(); 191 $prerequisites_complete = 0; 192 193 // Loop through course criteria 194 foreach ($completions as $completion) { 195 $criteria = $completion->get_criteria(); 196 $complete = $completion->is_complete(); 197 198 // Activities are a special case, so cache them and leave them till last 199 if ($criteria->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) { 200 $activities[$criteria->moduleinstance] = $complete; 201 202 if ($complete) { 203 $activities_complete++; 204 } 205 206 continue; 207 } 208 209 // Prerequisites are also a special case, so cache them and leave them till last 210 if ($criteria->criteriatype == COMPLETION_CRITERIA_TYPE_COURSE) { 211 $prerequisites[$criteria->courseinstance] = $complete; 212 213 if ($complete) { 214 $prerequisites_complete++; 215 } 216 217 continue; 218 } 219 220 $row = array(); 221 $row['title'] = $criteria->get_title(); 222 $row['status'] = $completion->get_status(); 223 $rows[] = $row; 224 } 225 226 // Aggregate activities 227 if (!empty($activities)) { 228 229 $row = array(); 230 $row['title'] = get_string('activitiescomplete', 'report_completion'); 231 $row['status'] = $activities_complete.' of '.count($activities); 232 $rows[] = $row; 233 } 234 235 // Aggregate prerequisites 236 if (!empty($prerequisites)) { 237 238 $row = array(); 239 $row['title'] = get_string('prerequisitescompleted', 'completion'); 240 $row['status'] = $prerequisites_complete.' of '.count($prerequisites); 241 array_splice($rows, 0, 0, array($row)); 242 } 243 244 $first_row = true; 245 246 // Print table 247 foreach ($rows as $row) { 248 249 // Display course name on first row 250 if ($first_row) { 251 echo '<tr><td class="c0"><a href="'.$CFG->wwwroot.'/course/view.php?id='.$c_course->id.'">'.$course_name.'</a></td>'; 252 } else { 253 echo '<tr><td class="c0"></td>'; 254 } 255 256 echo '<td class="c1">'; 257 echo $row['title']; 258 echo '</td><td class="c2">'; 259 260 switch ($row['status']) { 261 case 'Yes': 262 echo get_string('complete'); 263 break; 264 265 case 'No': 266 echo get_string('incomplete', 'report_completion'); 267 break; 268 269 default: 270 echo $row['status']; 271 } 272 273 // Display link on first row 274 echo '</td><td class="c3">'; 275 if ($first_row) { 276 echo '<a href="'.$CFG->wwwroot.'/blocks/completionstatus/details.php?course='.$c_course->id.'&user='.$user->id.'">'.get_string('detailedview', 'report_completion').'</a>'; 277 } 278 echo '</td>'; 279 280 // Display completion date for completed courses on first row 281 if ($type === 'complete' && $first_row) { 282 $params = array( 283 'userid' => $user->id, 284 'course' => $c_course->id 285 ); 286 287 $ccompletion = new completion_completion($params); 288 echo '<td class="c4">'.userdate($ccompletion->timecompleted, '%e %B %G').'</td>'; 289 } 290 291 $first_row = false; 292 echo '</tr>'; 293 } 294 } 295 296 echo '</table>'; 297 } 298} 299 300 301echo $OUTPUT->footer(); 302// Trigger a user report viewed event. 303$event = \report_completion\event\user_report_viewed::create(array('context' => $coursecontext, 'relateduserid' => $userid)); 304$event->trigger(); 305