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