MDL-30975 Docs Documenting report/logs
[moodle.git] / report / log / locallib.php
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/>.
17 /**
18  * This file contains functions used by the log reports
19  *
20  * This files lists the functions that are used during the log report generation.
21  *
22  * @package    report
23  * @subpackage log
24  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
25  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  */
28 defined('MOODLE_INTERNAL') || die;
30 if (!defined('REPORT_LOG_MAX_DISPLAY')) {
31     define('REPORT_LOG_MAX_DISPLAY', 150); // days
32 }
34 require_once(dirname(__FILE__).'/lib.php');
36 /**
37  * This function is used to generate and display the log activity graph
38  *
39  * @global object $CFG
40  * @param  object $course course instance
41  * @param  int    $userid id of the user whose logs are needed
42  * @param  string $type type of logs graph needed (usercourse.png/userday.png)
43  * @return void
44  */
45 function report_log_print_graph($course, $userid, $type, $date=0) {
46     global $CFG;
48     if (empty($CFG->gdversion)) {
49         echo "(".get_string("gdneed").")";
50     } else {
51         echo '<img src="'.$CFG->wwwroot.'/report/log/graph.php?id='.$course->id.
52              '&amp;user='.$userid.'&amp;type='.$type.'&amp;date='.$date.'" alt="" />';
53     }
54 }
55 /**
56  * This function is used to generate and display Mnet selector form
57  *
58  * @global object $USER
59  * @global object $CFG
60  * @global object $SITE
61  * @global object $DB
62  * @global object $OUTPUT
63  * @global object $SESSION
64  * @uses CONTEXT_SYSTEM
65  * @uses COURSE_MAX_COURSES_PER_DROPDOWN
66  * @uses CONTEXT_COURSE
67  * @uses SEPARATEGROUPS
68  * @param  int    $hostid host id
69  * @param  object $course course instance
70  * @param  int    $selecteduser id of the selected user
71  * @param  string $selecteddate Date selected
72  * @param  string $modname course_module->id
73  * @param  string $modid number or 'site_errors'
74  * @param  string $modaction an action as recorded in the logs
75  * @param  int    $selectedgroup Group to display
76  * @param  int    $showcourses whether to show courses if we're over our limit.
77  * @param  int    $showusers whether to show users if we're over our limit.
78  * @param  string $logformat Format of the logs (downloadascsv, showashtml, downloadasods, downloadasexcel)
79  * @return void
80  */
81 function report_log_print_mnet_selector_form($hostid, $course, $selecteduser=0, $selecteddate='today',
82                                  $modname="", $modid=0, $modaction='', $selectedgroup=-1, $showcourses=0, $showusers=0, $logformat='showashtml') {
84     global $USER, $CFG, $SITE, $DB, $OUTPUT, $SESSION;
85     require_once $CFG->dirroot.'/mnet/peer.php';
87     $mnet_peer = new mnet_peer();
88     $mnet_peer->set_id($hostid);
90     $sql = "SELECT DISTINCT course, hostid, coursename FROM {mnet_log}";
91     $courses = $DB->get_records_sql($sql);
92     $remotecoursecount = count($courses);
94     // first check to see if we can override showcourses and showusers
95     $numcourses = $remotecoursecount + $DB->count_records('course');
96     if ($numcourses < COURSE_MAX_COURSES_PER_DROPDOWN && !$showcourses) {
97         $showcourses = 1;
98     }
100     $sitecontext = get_context_instance(CONTEXT_SYSTEM);
102     // Context for remote data is always SITE
103     // Groups for remote data are always OFF
104     if ($hostid == $CFG->mnet_localhost_id) {
105         $context = get_context_instance(CONTEXT_COURSE, $course->id);
107         /// Setup for group handling.
108         if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
109             $selectedgroup = -1;
110             $showgroups = false;
111         } else if ($course->groupmode) {
112             $showgroups = true;
113         } else {
114             $selectedgroup = 0;
115             $showgroups = false;
116         }
118         if ($selectedgroup === -1) {
119             if (isset($SESSION->currentgroup[$course->id])) {
120                 $selectedgroup =  $SESSION->currentgroup[$course->id];
121             } else {
122                 $selectedgroup = groups_get_all_groups($course->id, $USER->id);
123                 if (is_array($selectedgroup)) {
124                     $selectedgroup = array_shift(array_keys($selectedgroup));
125                     $SESSION->currentgroup[$course->id] = $selectedgroup;
126                 } else {
127                     $selectedgroup = 0;
128                 }
129             }
130         }
132     } else {
133         $context = $sitecontext;
134     }
136     // Get all the possible users
137     $users = array();
139     // Define limitfrom and limitnum for queries below
140     // If $showusers is enabled... don't apply limitfrom and limitnum
141     $limitfrom = empty($showusers) ? 0 : '';
142     $limitnum  = empty($showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : '';
144     // If looking at a different host, we're interested in all our site users
145     if ($hostid == $CFG->mnet_localhost_id && $course->id != SITEID) {
146         $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, u.firstname, u.lastname, u.idnumber', 'lastname ASC, firstname ASC', $limitfrom, $limitnum);
147     } else {
148         // this may be a lot of users :-(
149         $courseusers = $DB->get_records('user', array('deleted'=>0), 'lastaccess DESC', 'id, firstname, lastname, idnumber', $limitfrom, $limitnum);
150     }
152     if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$showusers) {
153         $showusers = 1;
154     }
156     if ($showusers) {
157         if ($courseusers) {
158             foreach ($courseusers as $courseuser) {
159                 $users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context));
160             }
161         }
162         $users[$CFG->siteguest] = get_string('guestuser');
163     }
165     // Get all the hosts that have log records
166     $sql = "select distinct
167                 h.id,
168                 h.name
169             from
170                 {mnet_host} h,
171                 {mnet_log} l
172             where
173                 h.id = l.hostid
174             order by
175                 h.name";
177     if ($hosts = $DB->get_records_sql($sql)) {
178         foreach($hosts as $host) {
179             $hostarray[$host->id] = $host->name;
180         }
181     }
183     $hostarray[$CFG->mnet_localhost_id] = $SITE->fullname;
184     asort($hostarray);
186     $dropdown = array();
188     foreach($hostarray as $hostid => $name) {
189         $courses = array();
190         $sites = array();
191         if ($CFG->mnet_localhost_id == $hostid) {
192             if (has_capability('report/log:view', $sitecontext) && $showcourses) {
193                 if ($ccc = $DB->get_records("course", null, "fullname","id,fullname,category")) {
194                     foreach ($ccc as $cc) {
195                         if ($cc->id == SITEID) {
196                             $sites["$hostid/$cc->id"]   = format_string($cc->fullname).' ('.get_string('site').')';
197                         } else {
198                             $courses["$hostid/$cc->id"] = format_string($cc->fullname);
199                         }
200                     }
201                 }
202             }
203         } else {
204             if (has_capability('report/log:view', $sitecontext) && $showcourses) {
205                 $sql = "SELECT DISTINCT course, coursename FROM {mnet_log} where hostid = ?";
206                 if ($ccc = $DB->get_records_sql($sql, array($hostid))) {
207                     foreach ($ccc as $cc) {
208                         if (1 == $cc->course) { // TODO: this might be wrong - site course may have another id
209                             $sites["$hostid/$cc->course"]   = $cc->coursename.' ('.get_string('site').')';
210                         } else {
211                             $courses["$hostid/$cc->course"] = $cc->coursename;
212                         }
213                     }
214                 }
215             }
216         }
218         asort($courses);
219         $dropdown[] = array($name=>($sites + $courses));
220     }
223     $activities = array();
224     $selectedactivity = "";
226 /// Casting $course->modinfo to string prevents one notice when the field is null
227     if ($modinfo = unserialize((string)$course->modinfo)) {
228         $section = 0;
229         $sections = get_all_sections($course->id);
230         foreach ($modinfo as $mod) {
231             if ($mod->mod == "label") {
232                 continue;
233             }
234             if ($mod->section > 0 and $section <> $mod->section) {
235                 $activities["section/$mod->section"] = '--- '.get_section_name($course, $sections[$mod->section]).' ---';
236             }
237             $section = $mod->section;
238             $mod->name = strip_tags(format_string($mod->name, true));
239             if (textlib::strlen($mod->name) > 55) {
240                 $mod->name = textlib::substr($mod->name, 0, 50)."...";
241             }
242             if (!$mod->visible) {
243                 $mod->name = "(".$mod->name.")";
244             }
245             $activities["$mod->cm"] = $mod->name;
247             if ($mod->cm == $modid) {
248                 $selectedactivity = "$mod->cm";
249             }
250         }
251     }
253     if (has_capability('report/log:view', $sitecontext) && !$course->category) {
254         $activities["site_errors"] = get_string("siteerrors");
255         if ($modid === "site_errors") {
256             $selectedactivity = "site_errors";
257         }
258     }
260     $strftimedate = get_string("strftimedate");
261     $strftimedaydate = get_string("strftimedaydate");
263     asort($users);
265     // Prepare the list of action options.
266     $actions = array(
267         'view' => get_string('view'),
268         'add' => get_string('add'),
269         'update' => get_string('update'),
270         'delete' => get_string('delete'),
271         '-view' => get_string('allchanges')
272     );
274     // Get all the possible dates
275     // Note that we are keeping track of real (GMT) time and user time
276     // User time is only used in displays - all calcs and passing is GMT
278     $timenow = time(); // GMT
280     // What day is it now for the user, and when is midnight that day (in GMT).
281     $timemidnight = $today = usergetmidnight($timenow);
283     // Put today up the top of the list
284     $dates = array("$timemidnight" => get_string("today").", ".userdate($timenow, $strftimedate) );
286     if (!$course->startdate or ($course->startdate > $timenow)) {
287         $course->startdate = $course->timecreated;
288     }
290     $numdates = 1;
291     while ($timemidnight > $course->startdate and $numdates < 365) {
292         $timemidnight = $timemidnight - 86400;
293         $timenow = $timenow - 86400;
294         $dates["$timemidnight"] = userdate($timenow, $strftimedaydate);
295         $numdates++;
296     }
298     if ($selecteddate == "today") {
299         $selecteddate = $today;
300     }
302     echo "<form class=\"logselectform\" action=\"$CFG->wwwroot/report/log/index.php\" method=\"get\">\n";
303     echo "<div>\n";//invisible fieldset here breaks wrapping
304     echo "<input type=\"hidden\" name=\"chooselog\" value=\"1\" />\n";
305     echo "<input type=\"hidden\" name=\"showusers\" value=\"$showusers\" />\n";
306     echo "<input type=\"hidden\" name=\"showcourses\" value=\"$showcourses\" />\n";
307     if (has_capability('report/log:view', $sitecontext) && $showcourses) {
308         $cid = empty($course->id)? '1' : $course->id;
309         echo html_writer::select($dropdown, "host_course", $hostid.'/'.$cid);
310     } else {
311         $courses = array();
312         $courses[$course->id] = $course->fullname . ((empty($course->category)) ? ' ('.get_string('site').') ' : '');
313         echo html_writer::select($courses,"id",$course->id, false);
314         if (has_capability('report/log:view', $sitecontext)) {
315             $a = new stdClass();
316             $a->url = "$CFG->wwwroot/report/log/index.php?chooselog=0&group=$selectedgroup&user=$selecteduser"
317                 ."&id=$course->id&date=$selecteddate&modid=$selectedactivity&showcourses=1&showusers=$showusers";
318             print_string('logtoomanycourses','moodle',$a);
319         }
320     }
322     if ($showgroups) {
323         if ($cgroups = groups_get_all_groups($course->id)) {
324             foreach ($cgroups as $cgroup) {
325                 $groups[$cgroup->id] = $cgroup->name;
326             }
327         }
328         else {
329             $groups = array();
330         }
331         echo html_writer::select($groups, "group", $selectedgroup, get_string("allgroups"));
332     }
334     if ($showusers) {
335         echo html_writer::select($users, "user", $selecteduser, get_string("allparticipants"));
336     }
337     else {
338         $users = array();
339         if (!empty($selecteduser)) {
340             $user = $DB->get_record('user', array('id'=>$selecteduser));
341             $users[$selecteduser] = fullname($user);
342         }
343         else {
344             $users[0] = get_string('allparticipants');
345         }
346         echo html_writer::select($users, "user", $selecteduser, false);
347         $a->url = "$CFG->wwwroot/report/log/index.php?chooselog=0&group=$selectedgroup&user=$selecteduser"
348             ."&id=$course->id&date=$selecteddate&modid=$selectedactivity&showusers=1&showcourses=$showcourses";
349         print_string('logtoomanyusers','moodle',$a);
350     }
352     echo html_writer::select($dates, "date", $selecteddate, get_string("alldays"));
353     echo html_writer::select($activities, "modid", $selectedactivity, get_string("allactivities"));
354     echo html_writer::select($actions, 'modaction', $modaction, get_string("allactions"));
356     $logformats = array('showashtml' => get_string('displayonpage'),
357                         'downloadascsv' => get_string('downloadtext'),
358                         'downloadasods' => get_string('downloadods'),
359                         'downloadasexcel' => get_string('downloadexcel'));
360     echo html_writer::select($logformats, 'logformat', $logformat, false);
361     echo '<input type="submit" value="'.get_string('gettheselogs').'" />';
362     echo '</div>';
363     echo '</form>';
365 /**
366  * This function is used to generate and display selector form
367  *
368  * @global object $USER
369  * @global object $CFG
370  * @global object $DB
371  * @global object $OUTPUT
372  * @global object $SESSION
373  * @uses CONTEXT_SYSTEM
374  * @uses COURSE_MAX_COURSES_PER_DROPDOWN
375  * @uses CONTEXT_COURSE
376  * @uses SEPARATEGROUPS
377  * @param  object $course course instance
378  * @param  int    $selecteduser id of the selected user
379  * @param  string $selecteddate Date selected
380  * @param  string $modname course_module->id
381  * @param  string $modid number or 'site_errors'
382  * @param  string $modaction an action as recorded in the logs
383  * @param  int    $selectedgroup Group to display
384  * @param  int    $showcourses whether to show courses if we're over our limit.
385  * @param  int    $showusers whether to show users if we're over our limit.
386  * @param  string $logformat Format of the logs (downloadascsv, showashtml, downloadasods, downloadasexcel)
387  * @return void
388  */
389 function report_log_print_selector_form($course, $selecteduser=0, $selecteddate='today',
390                                  $modname="", $modid=0, $modaction='', $selectedgroup=-1, $showcourses=0, $showusers=0, $logformat='showashtml') {
392     global $USER, $CFG, $DB, $OUTPUT, $SESSION;
394     // first check to see if we can override showcourses and showusers
395     $numcourses =  $DB->count_records("course");
396     if ($numcourses < COURSE_MAX_COURSES_PER_DROPDOWN && !$showcourses) {
397         $showcourses = 1;
398     }
400     $sitecontext = get_context_instance(CONTEXT_SYSTEM);
401     $context = get_context_instance(CONTEXT_COURSE, $course->id);
403     /// Setup for group handling.
404     if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
405         $selectedgroup = -1;
406         $showgroups = false;
407     } else if ($course->groupmode) {
408         $showgroups = true;
409     } else {
410         $selectedgroup = 0;
411         $showgroups = false;
412     }
414     if ($selectedgroup === -1) {
415         if (isset($SESSION->currentgroup[$course->id])) {
416             $selectedgroup =  $SESSION->currentgroup[$course->id];
417         } else {
418             $selectedgroup = groups_get_all_groups($course->id, $USER->id);
419             if (is_array($selectedgroup)) {
420                 $selectedgroup = array_shift(array_keys($selectedgroup));
421                 $SESSION->currentgroup[$course->id] = $selectedgroup;
422             } else {
423                 $selectedgroup = 0;
424             }
425         }
426     }
428     // Get all the possible users
429     $users = array();
431     // Define limitfrom and limitnum for queries below
432     // If $showusers is enabled... don't apply limitfrom and limitnum
433     $limitfrom = empty($showusers) ? 0 : '';
434     $limitnum  = empty($showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : '';
436     $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, u.firstname, u.lastname', 'lastname ASC, firstname ASC', $limitfrom, $limitnum);
438     if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$showusers) {
439         $showusers = 1;
440     }
442     if ($showusers) {
443         if ($courseusers) {
444             foreach ($courseusers as $courseuser) {
445                 $users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context));
446             }
447         }
448         $users[$CFG->siteguest] = get_string('guestuser');
449     }
451     if (has_capability('report/log:view', $sitecontext) && $showcourses) {
452         if ($ccc = $DB->get_records("course", null, "fullname", "id,fullname,category")) {
453             foreach ($ccc as $cc) {
454                 if ($cc->category) {
455                     $courses["$cc->id"] = format_string($cc->fullname);
456                 } else {
457                     $courses["$cc->id"] = format_string($cc->fullname) . ' (Site)';
458                 }
459             }
460         }
461         asort($courses);
462     }
464     $activities = array();
465     $selectedactivity = "";
467 /// Casting $course->modinfo to string prevents one notice when the field is null
468     if ($modinfo = unserialize((string)$course->modinfo)) {
469         $section = 0;
470         $sections = get_all_sections($course->id);
471         foreach ($modinfo as $mod) {
472             if ($mod->mod == "label") {
473                 continue;
474             }
475             if ($mod->section > 0 and $section <> $mod->section) {
476                 $activities["section/$mod->section"] = '--- '.get_section_name($course, $sections[$mod->section]).' ---';
477             }
478             $section = $mod->section;
479             $mod->name = strip_tags(format_string($mod->name, true));
480             if (textlib::strlen($mod->name) > 55) {
481                 $mod->name = textlib::substr($mod->name, 0, 50)."...";
482             }
483             if (!$mod->visible) {
484                 $mod->name = "(".$mod->name.")";
485             }
486             $activities["$mod->cm"] = $mod->name;
488             if ($mod->cm == $modid) {
489                 $selectedactivity = "$mod->cm";
490             }
491         }
492     }
494     if (has_capability('report/log:view', $sitecontext) && ($course->id == SITEID)) {
495         $activities["site_errors"] = get_string("siteerrors");
496         if ($modid === "site_errors") {
497             $selectedactivity = "site_errors";
498         }
499     }
501     $strftimedate = get_string("strftimedate");
502     $strftimedaydate = get_string("strftimedaydate");
504     asort($users);
506     // Prepare the list of action options.
507     $actions = array(
508         'view' => get_string('view'),
509         'add' => get_string('add'),
510         'update' => get_string('update'),
511         'delete' => get_string('delete'),
512         '-view' => get_string('allchanges')
513     );
515     // Get all the possible dates
516     // Note that we are keeping track of real (GMT) time and user time
517     // User time is only used in displays - all calcs and passing is GMT
519     $timenow = time(); // GMT
521     // What day is it now for the user, and when is midnight that day (in GMT).
522     $timemidnight = $today = usergetmidnight($timenow);
524     // Put today up the top of the list
525     $dates = array("$timemidnight" => get_string("today").", ".userdate($timenow, $strftimedate) );
527     if (!$course->startdate or ($course->startdate > $timenow)) {
528         $course->startdate = $course->timecreated;
529     }
531     $numdates = 1;
532     while ($timemidnight > $course->startdate and $numdates < 365) {
533         $timemidnight = $timemidnight - 86400;
534         $timenow = $timenow - 86400;
535         $dates["$timemidnight"] = userdate($timenow, $strftimedaydate);
536         $numdates++;
537     }
539     if ($selecteddate == "today") {
540         $selecteddate = $today;
541     }
543     echo "<form class=\"logselectform\" action=\"$CFG->wwwroot/report/log/index.php\" method=\"get\">\n";
544     echo "<div>\n";
545     echo "<input type=\"hidden\" name=\"chooselog\" value=\"1\" />\n";
546     echo "<input type=\"hidden\" name=\"showusers\" value=\"$showusers\" />\n";
547     echo "<input type=\"hidden\" name=\"showcourses\" value=\"$showcourses\" />\n";
548     if (has_capability('report/log:view', $sitecontext) && $showcourses) {
549         echo html_writer::select($courses, "id", $course->id, false);
550     } else {
551         //        echo '<input type="hidden" name="id" value="'.$course->id.'" />';
552         $courses = array();
553         $courses[$course->id] = $course->fullname . (($course->id == SITEID) ? ' ('.get_string('site').') ' : '');
554         echo html_writer::select($courses,"id",$course->id, false);
555         if (has_capability('report/log:view', $sitecontext)) {
556             $a = new stdClass();
557             $a->url = "$CFG->wwwroot/report/log/index.php?chooselog=0&group=$selectedgroup&user=$selecteduser"
558                 ."&id=$course->id&date=$selecteddate&modid=$selectedactivity&showcourses=1&showusers=$showusers";
559             print_string('logtoomanycourses','moodle',$a);
560         }
561     }
563     if ($showgroups) {
564         if ($cgroups = groups_get_all_groups($course->id)) {
565             foreach ($cgroups as $cgroup) {
566                 $groups[$cgroup->id] = $cgroup->name;
567             }
568         }
569         else {
570             $groups = array();
571         }
572         echo html_writer::select($groups, "group", $selectedgroup, get_string("allgroups"));
573     }
575     if ($showusers) {
576         echo html_writer::select($users, "user", $selecteduser, get_string("allparticipants"));
577     }
578     else {
579         $users = array();
580         if (!empty($selecteduser)) {
581             $user = $DB->get_record('user', array('id'=>$selecteduser));
582             $users[$selecteduser] = fullname($user);
583         }
584         else {
585             $users[0] = get_string('allparticipants');
586         }
587         echo html_writer::select($users, "user", $selecteduser, false);
588         $a = new stdClass();
589         $a->url = "$CFG->wwwroot/report/log/index.php?chooselog=0&group=$selectedgroup&user=$selecteduser"
590             ."&id=$course->id&date=$selecteddate&modid=$selectedactivity&showusers=1&showcourses=$showcourses";
591         print_string('logtoomanyusers','moodle',$a);
592     }
593     echo html_writer::select($dates, "date", $selecteddate, get_string("alldays"));
595     echo html_writer::select($activities, "modid", $selectedactivity, get_string("allactivities"));
596     echo html_writer::select($actions, 'modaction', $modaction, get_string("allactions"));
598     $logformats = array('showashtml' => get_string('displayonpage'),
599                         'downloadascsv' => get_string('downloadtext'),
600                         'downloadasods' => get_string('downloadods'),
601                         'downloadasexcel' => get_string('downloadexcel'));
603     echo html_writer::select($logformats, 'logformat', $logformat, false);
604     echo '<input type="submit" value="'.get_string('gettheselogs').'" />';
605     echo '</div>';
606     echo '</form>';