24f2b65a |
1 | <?php // $Id$ |
f9903ed0 |
2 | |
97c270e9 |
3 | // Display user activity reports for a course |
4 | |
b0e3a925 |
5 | require_once("../config.php"); |
6 | require_once("lib.php"); |
f9903ed0 |
7 | |
f2a365b9 |
8 | $id = required_param('id',PARAM_INT); // course id |
9 | $user = required_param('user',PARAM_INT); // user id |
10 | $mode = optional_param('mode', "todaylogs", PARAM_ALPHA); |
11 | $page = optional_param('page', 0, PARAM_INT); |
96dcfb56 |
12 | $perpage = optional_param('perpage', 100, PARAM_INT); |
f9903ed0 |
13 | |
579d45b4 |
14 | if (!$course = $DB->get_record('course', array('id'=>$id))) { |
dbf91d9d |
15 | print_error('invalidcourseid', 'error'); |
f9903ed0 |
16 | } |
5bf04b36 |
17 | |
6bb08163 |
18 | if (! $user = $DB->get_record("user", array("id"=>$user))) { |
dbf91d9d |
19 | print_error('invaliduserid', 'error'); |
f9903ed0 |
20 | } |
5bf04b36 |
21 | |
f5fc83e8 |
22 | require_login(); |
358e2a0b |
23 | $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); |
24 | $personalcontext = get_context_instance(CONTEXT_USER, $user->id); |
25 | |
26 | require_login(); |
27 | if (has_capability('moodle/user:viewuseractivitiesreport', $personalcontext) and !has_capability('moodle/course:view', $coursecontext)) { |
28 | // do not require parents to be enrolled in courses ;-) |
c13a5e71 |
29 | $PAGE->set_course($course); |
358e2a0b |
30 | } else { |
31 | require_login($course); |
32 | } |
6bb91986 |
33 | |
f5fc83e8 |
34 | if ($user->deleted) { |
0a122046 |
35 | echo $OUTPUT->header(); |
7c5286cd |
36 | echo $OUTPUT->heading(get_string('userdeleted')); |
d60c1124 |
37 | echo $OUTPUT->footer(); |
f5fc83e8 |
38 | die; |
39 | } |
40 | |
358e2a0b |
41 | // prepare list of allowed modes |
42 | $myreports = ($course->showreports and $USER->id == $user->id); |
43 | $anyreport = has_capability('moodle/user:viewuseractivitiesreport', $personalcontext); |
44 | |
45 | $modes = array(); |
46 | |
47 | if ($myreports or $anyreport or has_capability('coursereport/outline:view', $coursecontext)) { |
48 | $modes[] = 'outline'; |
49 | } |
50 | |
51 | if ($myreports or $anyreport or has_capability('coursereport/outline:view', $coursecontext)) { |
52 | $modes[] = 'complete'; |
53 | } |
54 | |
55 | if ($myreports or $anyreport or has_capability('coursereport/log:viewtoday', $coursecontext)) { |
56 | $modes[] = 'todaylogs'; |
57 | } |
3924b988 |
58 | |
358e2a0b |
59 | if ($myreports or $anyreport or has_capability('coursereport/log:view', $coursecontext)) { |
60 | $modes[] = 'alllogs'; |
61 | } |
62 | |
63 | if ($myreports or $anyreport or has_capability('coursereport/stats:view', $coursecontext)) { |
64 | $modes[] = 'stats'; |
65 | } |
66 | |
67 | if (has_capability('moodle/grade:viewall', $coursecontext)) { |
68 | //ok - can view all course grades |
69 | $modes[] = 'grade'; |
70 | |
71 | } else if ($course->showgrades and $user->id == $USER->id and has_capability('moodle/grade:view', $coursecontext)) { |
72 | //ok - can view own grades |
73 | $modes[] = 'grade'; |
74 | |
75 | } else if ($course->showgrades and has_capability('moodle/grade:viewall', $personalcontext)) { |
76 | // ok - can view grades of this user - parent most probably |
77 | $modes[] = 'grade'; |
3c7da16d |
78 | |
79 | } else if ($course->showgrades and $anyreport) { |
80 | // ok - can view grades of this user - parent most probably |
81 | $modes[] = 'grade'; |
358e2a0b |
82 | } |
83 | |
84 | if (empty($modes)) { |
85 | require_capability('moodle/user:viewuseractivitiesreport', $personalcontext); |
86 | } |
87 | |
88 | if (!in_array($mode, $modes)) { |
89 | // forbidden or non-exitent mode |
90 | $mode = reset($modes); |
85a6e76c |
91 | } |
92 | |
0be6f678 |
93 | add_to_log($course->id, "course", "user report", "user.php?id=$course->id&user=$user->id&mode=$mode", "$user->id"); |
f9903ed0 |
94 | |
a2ab3b05 |
95 | $stractivityreport = get_string("activityreport"); |
96 | $strparticipants = get_string("participants"); |
97 | $stroutline = get_string("outline"); |
98 | $strcomplete = get_string("complete"); |
99 | $stralllogs = get_string("alllogs"); |
100 | $strtodaylogs = get_string("todaylogs"); |
101 | $strmode = get_string($mode); |
6f2e07e8 |
102 | $fullname = fullname($user, true); |
a2ab3b05 |
103 | |
0a122046 |
104 | $link = null; |
b26adbef |
105 | if ($course->id != SITEID && has_capability('moodle/course:viewparticipants', $coursecontext)) { |
0a122046 |
106 | $link = new moodle_url($CFG->wwwroot.'/user/index.php', array('id'=>$course->id)); |
a2ab3b05 |
107 | } |
91152a35 |
108 | $PAGE->navbar->add($strparticipants, $link); |
109 | $PAGE->navbar->add($fullname, new moodle_url($CFG->wwwroot.'/user/view.php', array('id'=>$user->id, 'course'=>$course->id))); |
0a122046 |
110 | $PAGE->navbar->add($stractivityreport); |
111 | $PAGE->navbar->add($strmode); |
112 | $PAGE->set_title("$course->shortname: $stractivityreport ($mode)"); |
113 | $PAGE->set_heading($course->fullname); |
114 | echo $OUTPUT->header(); |
f9a0ea69 |
115 | |
116 | /// Print tabs at top |
117 | /// This same call is made in: |
118 | /// /user/view.php |
119 | /// /user/edit.php |
120 | /// /course/user.php |
121 | $currenttab = $mode; |
b3e900ce |
122 | $showroles = 1; |
f9a0ea69 |
123 | include($CFG->dirroot.'/user/tabs.php'); |
124 | |
7468bf01 |
125 | switch ($mode) { |
7e2d7c92 |
126 | case "grade": |
0a784551 |
127 | if (empty($CFG->grade_profilereport) or !file_exists($CFG->dirroot.'/grade/report/'.$CFG->grade_profilereport.'/lib.php')) { |
128 | $CFG->grade_profilereport = 'user'; |
129 | } |
130 | require_once $CFG->libdir.'/gradelib.php'; |
131 | require_once $CFG->dirroot.'/grade/lib.php'; |
132 | require_once $CFG->dirroot.'/grade/report/'.$CFG->grade_profilereport.'/lib.php'; |
4d25a59e |
133 | |
0a784551 |
134 | $functionname = 'grade_report_'.$CFG->grade_profilereport.'_profilereport'; |
135 | if (function_exists($functionname)) { |
136 | $functionname($course, $user); |
f9c471df |
137 | } |
7e2d7c92 |
138 | break; |
0be6f678 |
139 | |
a2ab3b05 |
140 | case "todaylogs" : |
f9a0ea69 |
141 | echo '<div class="graph">'; |
adecd142 |
142 | print_log_graph($course, $user->id, "userday.png"); |
f9a0ea69 |
143 | echo '</div>'; |
0be6f678 |
144 | print_log($course, $user->id, usergetmidnight(time()), "l.time DESC", $page, $perpage, |
839f2456 |
145 | "user.php?id=$course->id&user=$user->id&mode=$mode"); |
2b8cef80 |
146 | break; |
147 | |
148 | case "alllogs" : |
f9a0ea69 |
149 | echo '<div class="graph">'; |
2b8cef80 |
150 | print_log_graph($course, $user->id, "usercourse.png"); |
f9a0ea69 |
151 | echo '</div>'; |
0be6f678 |
152 | print_log($course, $user->id, 0, "l.time DESC", $page, $perpage, |
839f2456 |
153 | "user.php?id=$course->id&user=$user->id&mode=$mode"); |
7468bf01 |
154 | break; |
f3221af9 |
155 | case 'stats': |
156 | |
157 | if (empty($CFG->enablestats)) { |
dbf91d9d |
158 | print_error('statsdisable', 'error'); |
f3221af9 |
159 | } |
160 | |
161 | require_once($CFG->dirroot.'/lib/statslib.php'); |
162 | |
13d32e22 |
163 | $statsstatus = stats_check_uptodate($course->id); |
164 | if ($statsstatus !== NULL) { |
e6db3026 |
165 | echo $OUTPUT->notification($statsstatus); |
13d32e22 |
166 | } |
140c139e |
167 | |
6bb08163 |
168 | $earliestday = $DB->get_field_sql('SELECT timeend FROM {stats_user_daily} ORDER BY timeend'); |
8f15f8ec |
169 | $earliestweek = $DB->get_field_sql('SELECT timeend FROM {stats_user_weekly} ORDER BY timeend'); |
6bb08163 |
170 | $earliestmonth = $DB->get_field_sql('SELECT timeend FROM {stats_user_monthly} ORDER BY timeend'); |
0be6f678 |
171 | |
f3221af9 |
172 | if (empty($earliestday)) $earliestday = time(); |
173 | if (empty($earliestweek)) $earliestweek = time(); |
174 | if (empty($earliestmonth)) $earliestmonth = time(); |
0be6f678 |
175 | |
f3221af9 |
176 | $now = stats_get_base_daily(); |
177 | $lastweekend = stats_get_base_weekly(); |
178 | $lastmonthend = stats_get_base_monthly(); |
179 | |
180 | $timeoptions = stats_get_time_options($now,$lastweekend,$lastmonthend,$earliestday,$earliestweek,$earliestmonth); |
181 | |
0be6f678 |
182 | if (empty($timeoptions)) { |
5a2a5331 |
183 | print_error('nostatstodisplay', '', $CFG->wwwroot.'/course/user.php?id='.$course->id.'&user='.$user->id.'&mode=outline'); |
f3221af9 |
184 | } |
185 | |
186 | // use the earliest. |
3a317277 |
187 | $time = array_pop(array_keys($timeoptions)); |
0be6f678 |
188 | |
3eb9babc |
189 | $param = stats_get_parameters($time,STATS_REPORT_USER_VIEW,$course->id,STATS_MODE_DETAILED); |
6bb08163 |
190 | $params = $param->params; |
f3221af9 |
191 | |
192 | $param->table = 'user_'.$param->table; |
3eb9babc |
193 | |
6bb08163 |
194 | $sql = 'SELECT timeend,'.$param->fields.' FROM {stats_'.$param->table.'} WHERE ' |
3a317277 |
195 | .(($course->id == SITEID) ? '' : ' courseid = '.$course->id.' AND ') |
6bb08163 |
196 | .' userid = '.$user->id.' AND timeend >= '.$param->timeafter .$param->extras |
f3221af9 |
197 | .' ORDER BY timeend DESC'; |
6bb08163 |
198 | $stats = $DB->get_records_sql($sql, $params); //TODO: improve these params!! |
3a317277 |
199 | |
200 | if (empty($stats)) { |
5a2a5331 |
201 | print_error('nostatstodisplay', '', $CFG->wwwroot.'/course/user.php?id='.$course->id.'&user='.$user->id.'&mode=outline'); |
3a317277 |
202 | } |
0be6f678 |
203 | |
3aafb7d9 |
204 | // MDL-10818, do not display broken graph when user has no permission to view graph |
358e2a0b |
205 | if ($myreports or has_capability('coursereport/stats:view', $coursecontext)) { |
3aafb7d9 |
206 | echo '<center><img src="'.$CFG->wwwroot.'/course/report/stats/graph.php?mode='.STATS_MODE_DETAILED.'&course='.$course->id.'&time='.$time.'&report='.STATS_REPORT_USER_VIEW.'&userid='.$user->id.'" alt="'.get_string('statisticsgraph').'" /></center>'; |
207 | } |
3eb9babc |
208 | |
e8e64fa3 |
209 | // What the heck is this about? -- MD |
3eb9babc |
210 | $stats = stats_fix_zeros($stats,$param->timeafter,$param->table,(!empty($param->line2)),(!empty($param->line3))); |
e8e64fa3 |
211 | |
b4531207 |
212 | $table = new html_table(); |
f3221af9 |
213 | $table->align = array('left','center','center','center'); |
214 | $param->table = str_replace('user_','',$param->table); |
61460dd6 |
215 | switch ($param->table) { |
216 | case 'daily' : $period = get_string('day'); break; |
217 | case 'weekly' : $period = get_string('week'); break; |
218 | case 'monthly': $period = get_string('month', 'form'); break; |
219 | default : $period = ''; |
220 | } |
221 | $table->head = array(get_string('periodending','moodle',$period),$param->line1,$param->line2,$param->line3); |
e8e64fa3 |
222 | foreach ($stats as $stat) { |
223 | if (!empty($stat->zerofixed)) { // Don't know why this is necessary, see stats_fix_zeros above - MD |
224 | continue; |
225 | } |
404fe839 |
226 | $a = array(userdate($stat->timeend,get_string('strftimedate'),$CFG->timezone),$stat->line1); |
f3221af9 |
227 | $a[] = $stat->line2; |
228 | $a[] = $stat->line3; |
229 | $table->data[] = $a; |
230 | } |
b4531207 |
231 | echo $OUTPUT->table($table); |
f3221af9 |
232 | break; |
358e2a0b |
233 | |
7468bf01 |
234 | case "outline" : |
235 | case "complete" : |
358e2a0b |
236 | get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused); |
7468bf01 |
237 | $sections = get_all_sections($course->id); |
600149be |
238 | |
7468bf01 |
239 | for ($i=0; $i<=$course->numsections; $i++) { |
240 | |
241 | if (isset($sections[$i])) { // should always be true |
242 | |
243 | $section = $sections[$i]; |
15850dcb |
244 | $showsection = (has_capability('moodle/course:viewhiddensections', $coursecontext) or $section->visible or !$course->hiddensections); |
7468bf01 |
245 | |
1757627a |
246 | if ($showsection) { // prevent hidden sections in user activity. Thanks to Geoff Wilbert! |
7468bf01 |
247 | |
1757627a |
248 | if ($section->sequence) { |
f9a0ea69 |
249 | echo '<div class="section">'; |
250 | echo '<h2>'; |
1757627a |
251 | switch ($course->format) { |
252 | case "weeks": print_string("week"); break; |
253 | case "topics": print_string("topic"); break; |
254 | default: print_string("section"); break; |
7af6281f |
255 | } |
1757627a |
256 | echo " $i</h2>"; |
0be6f678 |
257 | |
f9a0ea69 |
258 | echo '<div class="content">'; |
4f91674c |
259 | |
1757627a |
260 | if ($mode == "outline") { |
261 | echo "<table cellpadding=\"4\" cellspacing=\"0\">"; |
4f91674c |
262 | } |
263 | |
1757627a |
264 | $sectionmods = explode(",", $section->sequence); |
265 | foreach ($sectionmods as $sectionmod) { |
266 | if (empty($mods[$sectionmod])) { |
267 | continue; |
268 | } |
269 | $mod = $mods[$sectionmod]; |
0be6f678 |
270 | |
1757627a |
271 | if (empty($mod->visible)) { |
272 | continue; |
273 | } |
359b138b |
274 | |
6bb08163 |
275 | $instance = $DB->get_record("$mod->modname", array("id"=>$mod->instance)); |
1757627a |
276 | $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php"; |
277 | |
278 | if (file_exists($libfile)) { |
279 | require_once($libfile); |
280 | |
281 | switch ($mode) { |
282 | case "outline": |
283 | $user_outline = $mod->modname."_user_outline"; |
284 | if (function_exists($user_outline)) { |
285 | $output = $user_outline($course, $user, $mod, $instance); |
286 | print_outline_row($mod, $instance, $output); |
287 | } |
288 | break; |
289 | case "complete": |
290 | $user_complete = $mod->modname."_user_complete"; |
291 | if (function_exists($user_complete)) { |
292 | $image = "<img src=\"../mod/$mod->modname/icon.gif\" ". |
0d905d9f |
293 | "class=\"icon\" alt=\"$mod->modfullname\" />"; |
1757627a |
294 | echo "<h4>$image $mod->modfullname: ". |
295 | "<a href=\"$CFG->wwwroot/mod/$mod->modname/view.php?id=$mod->id\">". |
46043aff |
296 | format_string($instance->name,true)."</a></h4>"; |
0be6f678 |
297 | |
d76be18f |
298 | ob_start(); |
299 | |
1757627a |
300 | echo "<ul>"; |
301 | $user_complete($course, $user, $mod, $instance); |
302 | echo "</ul>"; |
d76be18f |
303 | |
d76be18f |
304 | $output = ob_get_contents(); |
4b9842d2 |
305 | ob_end_clean(); |
0be6f678 |
306 | |
d76be18f |
307 | if (str_replace(' ', '', $output) != '<ul></ul>') { |
308 | echo $output; |
309 | } |
1757627a |
310 | } |
311 | break; |
359b138b |
312 | } |
1757627a |
313 | } |
7468bf01 |
314 | } |
0be6f678 |
315 | |
1757627a |
316 | if ($mode == "outline") { |
317 | echo "</table>"; |
7468bf01 |
318 | } |
f9a0ea69 |
319 | echo '</div>'; // content |
320 | echo '</div>'; // section |
7468bf01 |
321 | } |
7468bf01 |
322 | } |
600149be |
323 | } |
f9903ed0 |
324 | } |
7468bf01 |
325 | break; |
358e2a0b |
326 | default: |
327 | // can not be reached ;-) |
f9903ed0 |
328 | } |
329 | |
7468bf01 |
330 | |
d60c1124 |
331 | echo $OUTPUT->footer(); |
f9903ed0 |
332 | |
7468bf01 |
333 | |
359b138b |
334 | function print_outline_row($mod, $instance, $result) { |
e63f88c9 |
335 | global $OUTPUT; |
bad35380 |
336 | |
e63f88c9 |
337 | $image = "<img src=\"" . $OUTPUT->mod_icon_url('icon', $mod->modname) . "\" class=\"icon\" alt=\"$mod->modfullname\" />"; |
24f2b65a |
338 | |
339 | echo "<tr>"; |
340 | echo "<td valign=\"top\">$image</td>"; |
fbe31d22 |
341 | echo "<td valign=\"top\" style=\"width:300\">"; |
24f2b65a |
342 | echo " <a title=\"$mod->modfullname\""; |
46043aff |
343 | echo " href=\"../mod/$mod->modname/view.php?id=$mod->id\">".format_string($instance->name,true)."</a></td>"; |
24f2b65a |
344 | echo "<td> </td>"; |
1530c97c |
345 | echo "<td valign=\"top\">"; |
359b138b |
346 | if (isset($result->info)) { |
347 | echo "$result->info"; |
348 | } else { |
fbe31d22 |
349 | echo "<p style=\"text-align:center\">-</p>"; |
359b138b |
350 | } |
24f2b65a |
351 | echo "</td>"; |
352 | echo "<td> </td>"; |
20affd15 |
353 | if (!empty($result->time)) { |
359b138b |
354 | $timeago = format_time(time() - $result->time); |
fbe31d22 |
355 | echo "<td valign=\"top\" style=\"white-space: nowrap\">".userdate($result->time)." ($timeago)</td>"; |
359b138b |
356 | } |
24f2b65a |
357 | echo "</tr>"; |
7468bf01 |
358 | } |
359 | |
f9903ed0 |
360 | ?> |