f5f12fa9e42d6abb6591c7d0142e9f3de513874d
[moodle.git] / report / log / classes / renderable.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  * Log report renderer.
19  *
20  * @package    report_log
21  * @copyright  2014 Rajesh Taneja <rajesh.taneja@gmail.com>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die;
26 use core\log\manager;
28 /**
29  * Report log renderable class.
30  *
31  * @package    report_log
32  * @copyright  2014 Rajesh Taneja <rajesh.taneja@gmail.com>
33  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34  */
35 class report_log_renderable implements renderable {
36     /** @var manager log manager */
37     protected $logmanager;
39     /** @var string selected log reader pluginname */
40     public $selectedlogreader = null;
42     /** @var int page number */
43     public $page;
45     /** @var int perpage records to show */
46     public $perpage;
48     /** @var stdClass course record */
49     public $course;
51     /** @var moodle_url url of report page */
52     public $url;
54     /** @var int selected date from which records should be displayed */
55     public $date;
57     /** @var int selected user id for which logs are displayed */
58     public $userid;
60     /** @var int selected moduleid */
61     public $modid;
63     /** @var string selected action filter */
64     public $action;
66     /** @var int educational level */
67     public $edulevel;
69     /** @var bool show courses */
70     public $showcourses;
72     /** @var bool show users */
73     public $showusers;
75     /** @var bool show report */
76     public $showreport;
78     /** @var bool show selector form */
79     public $showselectorform;
81     /** @var string selected log format */
82     public $logformat;
84     /** @var string order to sort */
85     public $order;
87     /** @var string origin to filter event origin */
88     public $origin;
90     /** @var int group id */
91     public $groupid;
93     /** @var table_log table log which will be used for rendering logs */
94     public $tablelog;
96     /**
97      * Constructor.
98      *
99      * @param string $logreader (optional)reader pluginname from which logs will be fetched.
100      * @param stdClass|int $course (optional) course record or id
101      * @param int $userid (optional) id of user to filter records for.
102      * @param int|string $modid (optional) module id or site_errors for filtering errors.
103      * @param string $action (optional) action name to filter.
104      * @param int $groupid (optional) groupid of user.
105      * @param int $edulevel (optional) educational level.
106      * @param bool $showcourses (optional) show courses.
107      * @param bool $showusers (optional) show users.
108      * @param bool $showreport (optional) show report.
109      * @param bool $showselectorform (optional) show selector form.
110      * @param moodle_url|string $url (optional) page url.
111      * @param int $date date (optional) timestamp of start of the day for which logs will be displayed.
112      * @param string $logformat log format.
113      * @param int $page (optional) page number.
114      * @param int $perpage (optional) number of records to show per page.
115      * @param string $order (optional) sortorder of fetched records
116      */
117     public function __construct($logreader = "", $course = 0, $userid = 0, $modid = 0, $action = "", $groupid = 0, $edulevel = -1,
118             $showcourses = false, $showusers = false, $showreport = true, $showselectorform = true, $url = "", $date = 0,
119             $logformat='showashtml', $page = 0, $perpage = 100, $order = "timecreated ASC", $origin ='') {
121         global $PAGE;
123         // Use first reader as selected reader, if not passed.
124         if (empty($logreader)) {
125             $readers = $this->get_readers();
126             if (!empty($readers)) {
127                 reset($readers);
128                 $logreader = key($readers);
129             } else {
130                 $logreader = null;
131             }
132         }
133         // Use page url if empty.
134         if (empty($url)) {
135             $url = new moodle_url($PAGE->url);
136         } else {
137             $url = new moodle_url($url);
138         }
139         $this->selectedlogreader = $logreader;
140         $url->param('logreader', $logreader);
142         // Use site course id, if course is empty.
143         if (!empty($course) && is_int($course)) {
144             $course = get_course($course);
145         }
146         $this->course = $course;
148         $this->userid = $userid;
149         $this->date = $date;
150         $this->page = $page;
151         $this->perpage = $perpage;
152         $this->url = $url;
153         $this->order = $order;
154         $this->modid = $modid;
155         $this->action = $action;
156         $this->groupid = $groupid;
157         $this->edulevel = $edulevel;
158         $this->showcourses = $showcourses;
159         $this->showusers = $showusers;
160         $this->showreport = $showreport;
161         $this->showselectorform = $showselectorform;
162         $this->logformat = $logformat;
163         $this->origin = $origin;
164     }
166     /**
167      * Get a list of enabled sql_reader objects/name
168      *
169      * @param bool $nameonly if true only reader names will be returned.
170      * @return array core\log\sql_reader object or name.
171      */
172     public function get_readers($nameonly = false) {
173         if (!isset($this->logmanager)) {
174             $this->logmanager = get_log_manager();
175         }
177         $readers = $this->logmanager->get_readers('core\log\sql_reader');
178         if ($nameonly) {
179             foreach ($readers as $pluginname => $reader) {
180                 $readers[$pluginname] = $reader->get_name();
181             }
182         }
183         return $readers;
184     }
186     /**
187      * Helper function to return list of activities to show in selection filter.
188      *
189      * @return array list of activities.
190      */
191     public function get_activities_list() {
192         $activities = array();
194         // For site just return site errors option.
195         $sitecontext = context_system::instance();
196         if ($this->course->id == SITEID && has_capability('report/log:view', $sitecontext)) {
197             $activities["site_errors"] = get_string("siteerrors");
198             return $activities;
199         }
201         $modinfo = get_fast_modinfo($this->course);
202         if (!empty($modinfo->cms)) {
203             $section = 0;
204             $thissection = array();
205             foreach ($modinfo->cms as $cm) {
206                 if (!$cm->uservisible || !$cm->has_view()) {
207                     continue;
208                 }
209                 if ($cm->sectionnum > 0 and $section <> $cm->sectionnum) {
210                     $activities[] = $thissection;
211                     $thissection = array();
212                 }
213                 $section = $cm->sectionnum;
214                 $modname = strip_tags($cm->get_formatted_name());
215                 if (core_text::strlen($modname) > 55) {
216                     $modname = core_text::substr($modname, 0, 50)."...";
217                 }
218                 if (!$cm->visible) {
219                     $modname = "(".$modname.")";
220                 }
221                 $key = get_section_name($this->course, $cm->sectionnum);
222                 if (!isset($thissection[$key])) {
223                     $thissection[$key] = array();
224                 }
225                 $thissection[$key][$cm->id] = $modname;
226             }
227             if (!empty($thissection)) {
228                 $activities[] = $thissection;
229             }
230         }
231         return $activities;
232     }
234     /**
235      * Helper function to get selected group.
236      *
237      * @return int selected group.
238      */
239     public function get_selected_group() {
240         global $SESSION, $USER;
242         // No groups for system.
243         if (empty($this->course)) {
244             return 0;
245         }
247         $context = context_course::instance($this->course->id);
249         $selectedgroup = 0;
250         // Setup for group handling.
251         $groupmode = groups_get_course_groupmode($this->course);
252         if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
253             $selectedgroup = -1;
254         } else if ($groupmode) {
255             $selectedgroup = $this->groupid;
256         } else {
257             $selectedgroup = 0;
258         }
260         if ($selectedgroup === -1) {
261             if (isset($SESSION->currentgroup[$this->course->id])) {
262                 $selectedgroup = $SESSION->currentgroup[$this->course->id];
263             } else {
264                 $selectedgroup = groups_get_all_groups($this->course->id, $USER->id);
265                 if (is_array($selectedgroup)) {
266                     $groupids = array_keys($selectedgroup);
267                     $selectedgroup = array_shift($groupids);
268                     $SESSION->currentgroup[$this->course->id] = $selectedgroup;
269                 } else {
270                     $selectedgroup = 0;
271                 }
272             }
273         }
274         return $selectedgroup;
275     }
277     /**
278      * Return list of actions for log reader.
279      *
280      * @todo MDL-44528 Get list from log_store.
281      * @return array list of action options.
282      */
283     public function get_actions() {
284         $actions = array(
285                 'c' => get_string('create'),
286                 'r' => get_string('view'),
287                 'u' => get_string('update'),
288                 'd' => get_string('delete'),
289                 'cud' => get_string('allchanges')
290                 );
291         return $actions;
292     }
294     /**
295      * Return selected user fullname.
296      *
297      * @return string user fullname.
298      */
299     public function get_selected_user_fullname() {
300         $user = core_user::get_user($this->userid);
301         return fullname($user);
302     }
304     /**
305      * Return list of courses to show in selector.
306      *
307      * @return array list of courses.
308      */
309     public function get_course_list() {
310         global $DB, $SITE;
312         $courses = array();
314         $sitecontext = context_system::instance();
315         // First check to see if we can override showcourses and showusers.
316         $numcourses = $DB->count_records("course");
317         if ($numcourses < COURSE_MAX_COURSES_PER_DROPDOWN && !$this->showcourses) {
318             $this->showcourses = 1;
319         }
321         // Check if course filter should be shown.
322         if (has_capability('report/log:view', $sitecontext) && $this->showcourses) {
323             if ($courserecords = $DB->get_records("course", null, "fullname", "id,shortname,fullname,category")) {
324                 foreach ($courserecords as $course) {
325                     if ($course->id == SITEID) {
326                         $courses[$course->id] = format_string($course->fullname) . ' (' . get_string('site') . ')';
327                     } else {
328                         $courses[$course->id] = format_string(get_course_display_name_for_list($course));
329                     }
330                 }
331             }
332             core_collator::asort($courses);
333         }
334         return $courses;
335     }
337     /**
338      * Return list of groups.
339      *
340      * @return array list of groups.
341      */
342     public function get_group_list() {
344         // No groups for system.
345         if (empty($this->course)) {
346             return array();
347         }
349         $context = context_course::instance($this->course->id);
350         $groups = array();
351         $groupmode = groups_get_course_groupmode($this->course);
352         if (($groupmode == VISIBLEGROUPS) ||
353                 ($groupmode == SEPARATEGROUPS and has_capability('moodle/site:accessallgroups', $context))) {
354             // Get all groups.
355             if ($cgroups = groups_get_all_groups($this->course->id)) {
356                 foreach ($cgroups as $cgroup) {
357                     $groups[$cgroup->id] = $cgroup->name;
358                 }
359             }
360         }
361         return $groups;
362     }
364     /**
365      * Return list of users.
366      *
367      * @return array list of users.
368      */
369     public function get_user_list() {
370         global $CFG, $SITE;
372         $courseid = $SITE->id;
373         if (!empty($this->course)) {
374             $courseid = $this->course->id;
375         }
376         $context = context_course::instance($courseid);
377         $limitfrom = empty($this->showusers) ? 0 : '';
378         $limitnum  = empty($this->showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : '';
379         $courseusers = get_enrolled_users($context, '', $this->groupid, 'u.id, ' . get_all_user_name_fields(true, 'u'),
380                 null, $limitfrom, $limitnum);
382         if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$this->showusers) {
383             $this->showusers = 1;
384         }
386         $users = array();
387         if ($this->showusers) {
388             if ($courseusers) {
389                 foreach ($courseusers as $courseuser) {
390                      $users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context));
391                 }
392             }
393             $users[$CFG->siteguest] = get_string('guestuser');
394         }
395         return $users;
396     }
398     /**
399      * Return list of date options.
400      *
401      * @return array date options.
402      */
403     public function get_date_options() {
404         global $SITE;
406         $strftimedate = get_string("strftimedate");
407         $strftimedaydate = get_string("strftimedaydate");
409         // Get all the possible dates.
410         // Note that we are keeping track of real (GMT) time and user time.
411         // User time is only used in displays - all calcs and passing is GMT.
412         $timenow = time(); // GMT.
414         // What day is it now for the user, and when is midnight that day (in GMT).
415         $timemidnight = usergetmidnight($timenow);
417         // Put today up the top of the list.
418         $dates = array("$timemidnight" => get_string("today").", ".userdate($timenow, $strftimedate) );
420         // If course is empty, get it from frontpage.
421         $course = $SITE;
422         if (!empty($this->course)) {
423             $course = $this->course;
424         }
425         if (!$course->startdate or ($course->startdate > $timenow)) {
426             $course->startdate = $course->timecreated;
427         }
429         $numdates = 1;
430         while ($timemidnight > $course->startdate and $numdates < 365) {
431             $timemidnight = $timemidnight - 86400;
432             $timenow = $timenow - 86400;
433             $dates["$timemidnight"] = userdate($timenow, $strftimedaydate);
434             $numdates++;
435         }
436         return $dates;
437     }
439     /**
440      * Return list of components to show in selector.
441      *
442      * @return array list of origins.
443      */
444     public function get_origin_options() {
445         global $DB;
446         $origins = $DB->get_records_sql('select distinct origin from {logstore_standard_log} order by origin ASC');
447         $ret = array();
448         $ret[''] = get_string('allsources', 'report_log');
449         foreach ($origins as $origin) {
450             if (!empty($origin->origin)) {
451                 $ret[$origin->origin] = get_string($origin->origin, 'report_log');
452             }
453         }
454         return $ret;
455     }
457     /**
458      * Return list of edulevel.
459      *
460      * @todo MDL-44528 Get list from log_store.
461      * @return array list of edulevels.
462      */
463     public function get_edulevel_options() {
464         $edulevels = array(
465                     -1 => get_string("edulevel"),
466                     1 => get_string('edulevelteacher'),
467                     2 => get_string('edulevelparticipating'),
468                     0 => get_string('edulevelother')
469                     );
470         return $edulevels;
471     }
473     /**
474      * Setup table log.
475      */
476     public function setup_table() {
477         $readers = $this->get_readers();
479         $filter = new \stdClass();
480         if (!empty($this->course)) {
481             $filter->courseid = $this->course->id;
482         } else {
483             $filter->courseid = 0;
484         }
486         $filter->userid = $this->userid;
487         $filter->modid = $this->modid;
488         $filter->groupid = $this->get_selected_group();
489         $filter->logreader = $readers[$this->selectedlogreader];
490         $filter->edulevel = $this->edulevel;
491         $filter->action = $this->action;
492         $filter->date = $this->date;
493         $filter->orderby = $this->order;
494         $filter->origin = $this->origin;
495         // If showing site_errors.
496         if ('site_errors' === $this->modid) {
497             $filter->siteerrors = true;
498             $filter->modid = 0;
499         }
501         $this->tablelog = new report_log_table_log('report_log', $filter);
502         $this->tablelog->define_baseurl($this->url);
503         $this->tablelog->is_downloadable(true);
504         $this->tablelog->show_download_buttons_at(array(TABLE_P_BOTTOM));
505     }
507     /**
508      * Download logs in specified format.
509      */
510     public function download() {
511         $filename = 'logs_' . userdate(time(), get_string('backupnameformat', 'langconfig'), 99, false);
512         if ($this->course->id !== SITEID) {
513             $courseshortname = format_string($this->course->shortname, true,
514                     array('context' => context_course::instance($this->course->id)));
515             $filename = clean_filename('logs_' . $courseshortname . '_' . userdate(time(),
516                     get_string('backupnameformat', 'langconfig'), 99, false));
517         }
518         $this->tablelog->is_downloading($this->logformat, $filename);
519         $this->tablelog->out($this->perpage, false);
520     }