MDL-43681 report_log: Modified log report to use log readers

This commit is contained in:
Rajesh Taneja 2014-02-13 14:28:40 +08:00
parent 9b8555fbea
commit ac8976c8b5
10 changed files with 1483 additions and 528 deletions

View File

@ -0,0 +1,499 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Log report renderer.
*
* @package report_log
* @copyright 2014 Rajesh Taneja <rajesh.taneja@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
use core\log\manager;
/**
* Report log renderable class.
*
* @package report_log
* @copyright 2014 Rajesh Taneja <rajesh.taneja@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class report_log_renderable implements renderable {
/** @var manager log manager */
protected $logmanager;
/** @var string selected log reader pluginname */
public $selectedlogreader = null;
/** @var int page number */
public $page;
/** @var int perpage records to show */
public $perpage;
/** @var stdClass course record */
public $course;
/** @var moodle_url url of report page */
public $url;
/** @var int selected date from which records should be displayed */
public $date;
/** @var int selected user id for which logs are displayed */
public $userid;
/** @var int selected moduleid */
public $modid;
/** @var string selected action filter */
public $action;
/** @var int educational level */
public $edulevel;
/** @var bool show courses */
public $showcourses;
/** @var bool show users */
public $showusers;
/** @var bool show report */
public $showreport;
/** @var bool show selector form */
public $showselectorform;
/** @var string selected log format */
public $logformat;
/** @var string order to sort */
public $order;
/** @var int group id */
public $groupid;
/** @var table_log table log which will be used for rendering logs */
public $tablelog;
/**
* Constructor.
*
* @param string $logreader (optional)reader pluginname from which logs will be fetched.
* @param stdClass|int $course (optional) course record or id
* @param int $userid (optional) id of user to filter records for.
* @param int|string $modid (optional) module id or site_errors for filtering errors.
* @param string $action (optional) action name to filter.
* @param int $groupid (optional) groupid of user.
* @param int $edulevel (optional) educational level.
* @param bool $showcourses (optional) show courses.
* @param bool $showusers (optional) show users.
* @param bool $showreport (optional) show report.
* @param bool $showselectorform (optional) show selector form.
* @param moodle_url|string $url (optional) page url.
* @param int $date date (optional) from which records will be fetched.
* @param string $logformat log format.
* @param int $page (optional) page number.
* @param int $perpage (optional) number of records to show per page.
* @param string $order (optional) sortorder of fetched records
*/
public function __construct($logreader = "", $course = 0, $userid = 0, $modid = 0, $action = "", $groupid = 0, $edulevel = -1,
$showcourses = false, $showusers = false, $showreport = true, $showselectorform = true, $url = "", $date = 0,
$logformat='showashtml', $page = 0, $perpage = 100, $order = "timecreated ASC") {
global $PAGE;
// Use first reader as selected reader, if not passed.
if (empty($logreader)) {
$readers = $this->get_readers();
if (!empty($readers)) {
reset($readers);
$logreader = key($readers);
} else {
$logreader = null;
}
}
// Use page url if empty.
if (empty($url)) {
$url = new moodle_url($PAGE->url);
} else {
$url = new moodle_url($url);
}
$this->selectedlogreader = $logreader;
// Use site course id, if course is empty.
if (!empty($course) && is_int($course)) {
$course = get_course($course);
}
$this->course = $course;
$this->userid = $userid;
$this->date = $date;
$this->page = $page;
$this->perpage = $perpage;
$this->url = $url;
$this->order = $order;
$this->modid = $modid;
$this->action = $action;
$this->groupid = $groupid;
$this->edulevel = $edulevel;
$this->showcourses = $showcourses;
$this->showusers = $showusers;
$this->showreport = $showreport;
$this->showselectorform = $showselectorform;
$this->logformat = $logformat;
}
/**
* Get a list of enabled sql_select_reader objects/name
*
* @param bool $nameonly if true only reader names will be returned.
* @return array core\log\sql_select_reader object or name.
*/
public function get_readers($nameonly = false) {
if (!isset($this->manager)) {
$this->logmanager = get_log_manager();
}
$readers = $this->logmanager->get_readers('core\log\sql_select_reader');
if ($nameonly) {
foreach ($readers as $pluginname => $reader) {
$readers[$pluginname] = $reader->get_name();
}
}
return $readers;
}
/**
* Helper function to return list of activities to show in selection filter.
*
* @return array list of activities.
*/
public function get_activities_list() {
$activities = array();
// For site just return site errors option.
$sitecontext = context_system::instance();
if (empty($this->course) && has_capability('report/log:view', $sitecontext)) {
$activities["site_errors"] = get_string("siteerrors");
return $activities;
}
$modinfo = get_fast_modinfo($this->course);
if (!empty($modinfo->cms)) {
$section = 0;
$thissection = array();
foreach ($modinfo->cms as $cm) {
if (!$cm->uservisible || !$cm->has_view()) {
continue;
}
if ($cm->sectionnum > 0 and $section <> $cm->sectionnum) {
$activities[] = $thissection;
$thissection = array();
}
$section = $cm->sectionnum;
$modname = strip_tags($cm->get_formatted_name());
if (core_text::strlen($modname) > 55) {
$modname = core_text::substr($modname, 0, 50)."...";
}
if (!$cm->visible) {
$modname = "(".$modname.")";
}
$key = get_section_name($this->course, $cm->sectionnum);
if (!isset($thissection[$key])) {
$thissection[$key] = array();
}
$thissection[$key][$cm->id] = $modname;
}
if (!empty($thissection)) {
$activities[] = $thissection;
}
}
return $activities;
}
/**
* Helper function to get selected group.
*
* @return int selected group.
*/
public function get_selected_group() {
global $SESSION, $USER;
// No groups for system.
if (empty($this->course)) {
return 0;
}
$context = context_course::instance($this->course->id);
$selectedgroup = 0;
// Setup for group handling.
$groupmode = groups_get_course_groupmode($this->course);
if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
$selectedgroup = -1;
} else if ($groupmode) {
$selectedgroup = $this->groupid;
} else {
$selectedgroup = 0;
}
if ($selectedgroup === -1) {
if (isset($SESSION->currentgroup[$this->course->id])) {
$selectedgroup = $SESSION->currentgroup[$this->course->id];
} else {
$selectedgroup = groups_get_all_groups($this->course->id, $USER->id);
if (is_array($selectedgroup)) {
$groupids = array_keys($selectedgroup);
$selectedgroup = array_shift($groupids);
$SESSION->currentgroup[$this->course->id] = $selectedgroup;
} else {
$selectedgroup = 0;
}
}
}
return $selectedgroup;
}
/**
* Return list of actions for log reader.
*
* @todo MDL-44528 Get list from log_store.
* @return array list of action options.
*/
public function get_actions() {
$actions = array(
'c' => get_string('create'),
'r' => get_string('view'),
'u' => get_string('update'),
'd' => get_string('delete'),
'' => get_string('allchanges')
);
return $actions;
}
/**
* Return selected user fullname.
*
* @return string user fullname.
*/
public function get_selected_user_fullname() {
$user = core_user::get_user($this->userid);
return fullname($user);
}
/**
* Return list of courses to show in selector.
*
* @return array list of courses.
*/
public function get_course_list() {
global $DB, $SITE;
$courses = array();
$sitecontext = context_system::instance();
// First check to see if we can override showcourses and showusers.
$numcourses = $DB->count_records("course");
// Check if course filter should be shown.
if ((has_capability('report/log:view', $sitecontext)) && ($this->showcourses ||
(empty($this->showcourses) && ($numcourses < COURSE_MAX_COURSES_PER_DROPDOWN)))) {
$courses[0] = get_string('sitelogs');
$this->showcourses = true;
if ($courserecords = $DB->get_records("course", null, "fullname", "id,shortname,fullname,category")) {
foreach ($courserecords as $course) {
if ($course->category) {
$courses[$course->id] = format_string(get_course_display_name_for_list($course));
} else {
$courses[$course->id] = $SITE->shortname;
}
}
}
core_collator::asort($courses);
} else {
if (!empty($this->course->id)) {
$coursecontext = context_course::instance($this->course->id);
if (has_capability('report/log:view', $coursecontext)) {
$courses[$this->course->id] = format_string(get_course_display_name_for_list($this->course));
} else {
$this->showcourses = false;
}
} else {
$this->showcourses = false;
}
}
return $courses;
}
/**
* Return list of groups.
*
* @return array list of groups.
*/
public function get_group_list() {
// No groups for system.
if (empty($this->course)) {
return array();
}
$context = context_course::instance($this->course->id);
$groups = array();
$groupmode = groups_get_course_groupmode($this->course);
if (($groupmode == VISIBLEGROUPS) ||
($groupmode == SEPARATEGROUPS and has_capability('moodle/site:accessallgroups', $context))) {
// Get all groups.
if ($cgroups = groups_get_all_groups($this->course->id)) {
foreach ($cgroups as $cgroup) {
$groups[$cgroup->id] = $cgroup->name;
}
}
}
return $groups;
}
/**
* Return list of users.
*
* @return array list of users.
*/
public function get_user_list() {
global $CFG, $SITE;
$courseid = $SITE->id;
if (!empty($this->course)) {
$courseid = $this->course->id;
}
$context = context_course::instance($courseid);
$limitfrom = empty($this->showusers) ? 0 : '';
$limitnum = empty($this->showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : '';
$courseusers = get_enrolled_users($context, '', $this->groupid, 'u.id, ' . get_all_user_name_fields(true, 'u'),
null, $limitfrom, $limitnum);
$users = array();
if (($this->showusers) || (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && empty($this->showusers))) {
$this->showusers = true;
if ($courseusers) {
foreach ($courseusers as $courseuser) {
$users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context));
}
}
$users[$CFG->siteguest] = get_string('guestuser');
}
return $users;
}
/**
* Return list of date options.
*
* @return array date options.
*/
public function get_date_options() {
global $SITE;
$strftimedate = get_string("strftimedate");
$strftimedaydate = get_string("strftimedaydate");
// Get all the possible dates.
// Note that we are keeping track of real (GMT) time and user time.
// User time is only used in displays - all calcs and passing is GMT.
$timenow = time(); // GMT.
// What day is it now for the user, and when is midnight that day (in GMT).
$timemidnight = usergetmidnight($timenow);
// Put today up the top of the list.
$dates = array("$timemidnight" => get_string("today").", ".userdate($timenow, $strftimedate) );
// If course is empty, get it from frontpage.
$course = $SITE;
if (!empty($this->course)) {
$course = $this->course;
}
if (!$course->startdate or ($course->startdate > $timenow)) {
$course->startdate = $course->timecreated;
}
$numdates = 1;
while ($timemidnight > $course->startdate and $numdates < 365) {
$timemidnight = $timemidnight - 86400;
$timenow = $timenow - 86400;
$dates["$timemidnight"] = userdate($timenow, $strftimedaydate);
$numdates++;
}
return $dates;
}
/**
* Return list of edulevel.
*
* @todo MDL-44528 Get list from log_store.
* @return array list of edulevels.
*/
public function get_edulevel_options() {
$edulevels = array(
-1 => get_string("edulevel"),
1 => get_string('edulevelteacher'),
2 => get_string('edulevelparticipating'),
0 => get_string('edulevelother')
);
return $edulevels;
}
/**
* Setup table log.
*/
public function setup_table() {
$readers = $this->get_readers();
$filter = new \stdClass();
if (!empty($this->course)) {
$filter->courseid = $this->course->id;
} else {
$filter->courseid = 0;
}
$filter->userid = $this->userid;
$filter->modid = $this->modid;
$filter->groupid = $this->get_selected_group();
$filter->logreader = $readers[$this->selectedlogreader];
$filter->edulevel = $this->edulevel;
$filter->action = $this->action;
$filter->date = $this->date;
$filter->orderby = $this->order;
// If showing site_errors.
if ('site_errors' === $this->modid) {
$filter->siteerrors = true;
$filter->modid = 0;
}
$this->tablelog = new report_log_table_log('report_log', $filter);
$this->tablelog->define_baseurl($this->url);
$this->tablelog->is_downloadable(true);
$this->tablelog->show_download_buttons_at(array(TABLE_P_BOTTOM));
}
/**
* Download logs in specified format.
*/
public function download() {
$filename = 'logs_' . userdate(time(), get_string('backupnameformat', 'langconfig'), 99, false);
$this->tablelog->is_downloading($this->logformat, $filename);
$this->tablelog->out($this->perpage, false);
}
}

View File

@ -0,0 +1,177 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Log report renderer.
*
* @package report_log
* @copyright 2014 Rajesh Taneja <rajesh.taneja@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
/**
* Report log renderer's for printing reports.
*
* @package report_log
* @copyright 2014 Rajesh Taneja <rajesh.taneja@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class report_log_renderer extends plugin_renderer_base {
/**
* Render log report page.
*
* @param report_log_renderable $reportlog object of report_log.
*/
public function render_report_log_renderable(report_log_renderable $reportlog) {
if (empty($reportlog->selectedlogreader)) {
echo $this->output->notification(get_string('nologreaderenabled', 'report_log'), 'notifyproblem');
return;
}
if ($reportlog->showselectorform) {
$this->report_selector_form($reportlog);
}
if ($reportlog->showreport) {
$reportlog->tablelog->out($reportlog->perpage, true);
}
}
/**
* Prints/return reader selector
*
* @param report_log_renderable $reportlog log report.
*/
public function reader_selector(report_log_renderable $reportlog) {
$readers = $reportlog->get_readers(true);
if (empty($readers)) {
$readers = array(get_string('nologreaderenabled', 'report_log'));
}
$select = new single_select($reportlog->url, 'logreader', $readers, $reportlog->selectedlogreader, null);
$select->set_label(get_string('selectlogreader', 'report_log'));
echo $this->output->render($select);
}
/**
* This function is used to generate and display selector form
*
* @param report_log_renderable $reportlog log report.
*/
public function report_selector_form(report_log_renderable $reportlog) {
echo html_writer::start_tag('form', array('class' => 'logselecform', 'action' => $reportlog->url, 'method' => 'get'));
echo html_writer::start_div();
echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'chooselog', 'value' => '1'));
echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'showusers', 'value' => $reportlog->showusers));
echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'showcourses',
'value' => $reportlog->showcourses));
$selectedcourseid = empty($reportlog->course) ? 0 : $reportlog->course->id;
// Add course selector.
$courses = $reportlog->get_course_list();
if (!empty($courses)) {
if ($reportlog->showcourses) {
echo html_writer::label(get_string('selectacourse'), 'menuid', false, array('class' => 'accesshide'));
echo html_writer::select($courses, "id", $selectedcourseid, null);
} else {
$courseoption[$selectedcourseid] = $courses[$selectedcourseid];
unset($courses);
echo html_writer::label(get_string('selectacourse'), 'menuid', false, array('class' => 'accesshide'));
echo html_writer::select($courseoption, "id", $selectedcourseid, null);
// Check if user is admin and this came because of limitation on number of courses to show in dropdown.
$sitecontext = context_system::instance();
if (has_capability('report/log:view', $sitecontext)) {
$a = new stdClass();
$a->url = new moodle_url('/report/log/index.php', array('chooselog' => 0,
'group' => $reportlog->get_selected_group(), 'user' => $reportlog->userid,
'id' => $selectedcourseid, 'date' => $reportlog->date, 'modid' => $reportlog->modid,
'showcourses' => 1, 'showusers' => $reportlog->showusers));
print_string('logtoomanycourses', 'moodle', $a);
}
}
}
// Add group selector.
$groups = $reportlog->get_group_list();
if (!empty($groups)) {
echo html_writer::label(get_string('selectagroup'), 'menugroup', false, array('class' => 'accesshide'));
echo html_writer::select($groups, "group", $reportlog->groupid, get_string("allgroups"));
}
// Add user selector.
$users = $reportlog->get_user_list();
if (!empty($users)) {
if ($reportlog->showusers) {
echo html_writer::label(get_string('selctauser'), 'menuuser', false, array('class' => 'accesshide'));
echo html_writer::select($users, "user", $reportlog->userid, get_string("allparticipants"));
} else {
$users = array();
if (!empty($reportlog->userid)) {
$users[$reportlog->userid] = $reportlog->get_selected_user_fullname();
} else {
$users[0] = get_string('allparticipants');
}
echo html_writer::label(get_string('selctauser'), 'menuuser', false, array('class' => 'accesshide'));
echo html_writer::select($users, "user", $reportlog->userid, false);
$a = new stdClass();
$a->url = new moodle_url('/report/log/index.php', array('chooselog' => 0,
'group' => $reportlog->get_selected_group(), 'user' => $reportlog->userid,
'id' => $selectedcourseid, 'date' => $reportlog->date, 'modid' => $reportlog->modid,
'showcourses' => 1, 'showusers' => $reportlog->showusers, 'showcourses' => $reportlog->showcourses));
print_string('logtoomanyusers', 'moodle', $a);
}
}
// Add date selector.
$dates = $reportlog->get_date_options();
echo html_writer::label(get_string('date'), 'menudate', false, array('class' => 'accesshide'));
echo html_writer::select($dates, "date", $reportlog->date, get_string("alldays"));
// Add activity selector.
$activities = $reportlog->get_activities_list();
echo html_writer::label(get_string('activities'), 'menumodid', false, array('class' => 'accesshide'));
echo html_writer::select($activities, "modid", $reportlog->modid, get_string("allactivities"));
// Add actions selector.
echo html_writer::label(get_string('actions'), 'menumodaction', false, array('class' => 'accesshide'));
echo html_writer::select($reportlog->get_actions(), 'modaction', $reportlog->action, get_string("allactions"));
// Add edulevel.
$edulevel = $reportlog->get_edulevel_options();
echo html_writer::label(get_string('edulevel'), 'menuedulevel', false, array('class' => 'accesshide'));
echo html_writer::select($edulevel, 'edulevel', $reportlog->edulevel, false);
// Add reader option.
// If there is some reader available then only show submit button.
$readers = $reportlog->get_readers(true);
if (!empty($readers)) {
if (count($readers) == 1) {
$attributes = array('type' => 'hidden', 'name' => 'logreader', 'value' => key($readers));
echo html_writer::empty_tag('input', $attributes);
} else {
echo html_writer::label(get_string('selectlogreader', 'report_log'), 'menureader', false,
array('class' => 'accesshide'));
echo html_writer::select($readers, 'logreader', $reportlog->selectedlogreader, false);
}
echo html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('gettheselogs')));
}
echo html_writer::end_div();
echo html_writer::end_tag('form');
}
}

View File

@ -0,0 +1,438 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Table log for displaying logs.
*
* @package report_log
* @copyright 2014 Rajesh Taneja <rajesh.taneja@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
/**
* Table log class for displaying logs.
*
* @package report_log
* @copyright 2014 Rajesh Taneja <rajesh.taneja@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class report_log_table_log extends table_sql {
/** @var array list of user fullnames shown in report */
private $userfullnames = array();
/** @var array list of course short names shown in report */
private $courseshortnames = array();
/** @var array list of context name shown in report */
private $contextname = array();
/** @var stdClass filters parameters */
private $filterparams;
/**
* Sets up the table_log parameters.
*
* @param string $uniqueid unique id of form.
* @param stdClass $filterparams (optional) filter params.
* - int courseid: id of course
* - int userid: user id
* - int|string modid: Module id or "site_errors" to view site errors
* - int groupid: Group id
* - \core\log\sql_select_reader logreader: reader from which data will be fetched.
* - int edulevel: educational level.
* - string action: view action
* - int date: Date from which logs to be viewed.
*/
public function __construct($uniqueid, $filterparams = null) {
parent::__construct($uniqueid);
$this->set_attribute('class', 'reportlog generaltable generalbox');
$this->filterparams = $filterparams;
// Add course column if logs are displayed for site.
$cols = array();
$headers = array();
if (empty($filterparams->courseid)) {
$cols = array('course');
$headers = array(get_string('course'));
}
$this->define_columns(array_merge($cols, array('time', 'fullnameuser', 'relatedfullnameuser', 'context', 'component',
'eventname', 'description', 'origin', 'ip')));
$this->define_headers(array_merge($headers, array(
get_string('time'),
get_string('fullnameuser'),
get_string('eventrelatedfullnameuser', 'report_log'),
get_string('eventcontext', 'report_log'),
get_string('eventcomponent', 'report_log'),
get_string('eventname'),
get_string('description'),
get_string('eventorigin', 'report_log'),
get_string('ip_address')
)
));
$this->collapsible(false);
$this->sortable(false);
$this->pageable(true);
}
/**
* Generate the course column.
*
* @param stdClass $event event data.
* @return string HTML for the course column.
*/
public function col_course($event) {
if (empty($event->courseid) || empty($this->courseshortnames[$event->courseid])) {
return '-';
} else {
return $this->courseshortnames[$event->courseid];
}
}
/**
* Generate the time column.
*
* @param stdClass $event event data.
* @return string HTML for the time column
*/
public function col_time($event) {
$recenttimestr = get_string('strftimerecent', 'core_langconfig');
return userdate($event->timecreated, $recenttimestr);
}
/**
* Generate the username column.
*
* @param stdClass $event event data.
* @return string HTML for the username column
*/
public function col_fullnameuser($event) {
// Get extra event data for origin and realuserid.
$logextra = $event->get_logextra();
// Add username who did the action.
if (!empty($logextra['realuserid'])) {
$a = new stdClass();
$a->realusername = html_writer::link(new moodle_url("/user/view.php?id={$event->userid}&course={$event->courseid}"),
$this->userfullnames[$logextra['realuserid']]);
$a->asusername = html_writer::link(new moodle_url("/user/view.php?id={$event->userid}&course={$event->courseid}"),
$this->userfullnames[$event->userid]);
$username = get_string('eventloggedas', 'report_log', $a);
} else if (!empty($event->userid) && !empty($this->userfullnames[$event->userid])) {
$params = array('id' => $event->userid);
if ($event->courseid) {
$params['course'] = $event->courseid;
}
$username = html_writer::link(new moodle_url("/user/view.php", $params), $this->userfullnames[$event->userid]);
} else {
$username = '-';
}
return $username;
}
/**
* Generate the related username column.
*
* @param stdClass $event event data.
* @return string HTML for the related username column
*/
public function col_relatedfullnameuser($event) {
// Add affected user.
if (!empty($event->relateduserid)) {
return html_writer::link(new moodle_url("/user/view.php?id=" . $event->relateduserid . "&course=" .
$event->courseid), $this->userfullnames[$event->relateduserid]);
} else {
return '-';
}
}
/**
* Generate the context column.
*
* @param stdClass $event event data.
* @return string HTML for the context column
*/
public function col_context($event) {
// Add context name.
if ($event->contextid) {
// If context name was fetched before then return, else get one.
if (isset($this->contextname[$event->contextid])) {
return $this->contextname[$event->contextid];
} else {
$context = context::instance_by_id($event->contextid, IGNORE_MISSING);
if ($context) {
$contextname = $context->get_context_name(true);
if ($url = $context->get_url()) {
$contextname = html_writer::link($url, $contextname);
}
} else {
$contextname = get_string('other');
}
}
} else {
$contextname = get_string('other');
}
$this->contextname[$event->contextid] = $contextname;
return $contextname;
}
/**
* Generate the component column.
*
* @param stdClass $event event data.
* @return string HTML for the component column
*/
public function col_component($event) {
// Component.
$componentname = $event->component;
if (($event->component === 'core') || ($event->component === 'legacy')) {
return get_string('coresystem');
} else if (get_string_manager()->string_exists('pluginname', $event->component)) {
return get_string('pluginname', $event->component);
} else {
return $componentname;
}
}
/**
* Generate the event name column.
*
* @param stdClass $event event data.
* @return string HTML for the event name column
*/
public function col_eventname($event) {
// Event name.
$eventname = $event->get_name();
if ($url = $event->get_url()) {
$eventname = html_writer::link($url, $eventname);
}
return $eventname;
}
/**
* Generate the description column.
*
* @param stdClass $event event data.
* @return string HTML for the description column
*/
public function col_description($event) {
// Description.
return $event->get_description();
}
/**
* Generate the origin column.
*
* @param stdClass $event event data.
* @return string HTML for the origin column
*/
public function col_origin($event) {
// Get extra event data for origin and realuserid.
$logextra = $event->get_logextra();
// Add event origin, normally IP/cron.
return $logextra['origin'];
}
/**
* Generate the ip column.
*
* @param stdClass $event event data.
* @return string HTML for the ip column
*/
public function col_ip($event) {
// Get extra event data for origin and realuserid.
$logextra = $event->get_logextra();
$link = new moodle_url("/iplookup/index.php?ip={$logextra['ip']}&user=$event->userid");
return html_writer::link($link, $logextra['ip']);
}
/**
* Helper function to get legacy crud action.
*
* @param string $crud crud action
* @return string legacy action.
*/
public function get_legacy_crud_action($crud) {
$legacyactionmap = array('c' => 'add', 'r' => 'view', 'u' => 'update', 'd' => 'delete');
if (array_key_exists($crud, $legacyactionmap)) {
return $legacyactionmap[$crud];
} else {
// From old legacy log.
return '-view';
}
}
/**
* Helper function which is used by build logs to get action sql and param.
*
* @return array sql and param for action.
*/
public function get_action_sql() {
global $DB;
// In new logs we have a field to pick, and in legacy try get this from action.
if ($this->filterparams->logreader instanceof logstore_legacy\log\store) {
$action = $this->get_legacy_crud_action($this->filterparams->action);
$firstletter = substr($action, 0, 1);
if ($firstletter == '-') {
$sql = $DB->sql_like('action', ':action', false, true, true);
$params['action'] = '%'.substr($action, 1).'%';
} else {
$sql = $DB->sql_like('action', ':action', false);
$params['action'] = '%'.$action.'%';
}
} else {
$sql = "crud = :crud";
$params['crud'] = $this->filterparams->action;
}
return array($sql, $params);
}
/**
* Query the reader. Store results in the object for use by build_table.
*
* @param int $pagesize size of page for paginated displayed table.
* @param bool $useinitialsbar do you want to use the initials bar.
*/
public function query_db($pagesize, $useinitialsbar = true) {
$joins = array();
$params = array();
$groupid = 0;
if (!empty($this->filterparams->courseid)) {
if (!empty($this->filterparams->groupid)) {
$groupid = $this->filterparams->groupid;
}
$joins[] = "courseid = :courseid";
$params['courseid'] = $this->filterparams->courseid;
}
if (!empty($this->filterparams->siteerrors)) {
$joins[] = "( action='error' OR action='infected' OR action='failed' )";
}
if (!empty($this->filterparams->modid)) {
$joins[] = "contextinstanceid = :contextinstanceid";
$params['contextinstanceid'] = $this->filterparams->modid;
}
if (!empty($this->filterparams->action)) {
list($actionsql, $actionparams) = $this->get_action_sql();
$joins[] = $actionsql;
$params = array_merge($params, $actionparams);
}
// Getting all members of a group.
if ($groupid and empty($this->filterparams->userid)) {
if ($gusers = groups_get_members($groupid)) {
$gusers = array_keys($gusers);
$joins[] = 'userid IN (' . implode(',', $gusers) . ')';
} else {
$joins[] = 'userid = 0'; // No users in groups, so we want something that will always be false.
}
} else if (!empty($this->filterparams->userid)) {
$joins[] = "userid = :userid";
$params['userid'] = $this->filterparams->userid;
}
if (!empty($this->filterparams->date)) {
$joins[] = "timecreated > :date";
$params['date'] = $this->filterparams->date;
}
if (isset($this->filterparams->edulevel) && ($this->filterparams->edulevel >= 0)) {
$joins[] = "edulevel = :edulevel";
$params['edulevel'] = $this->filterparams->edulevel;
}
$selector = implode(' AND ', $joins);
if (!$this->is_downloading()) {
$total = $this->filterparams->logreader->get_events_select_count($selector, $params);
$this->pagesize($pagesize, $total);
}
$this->rawdata = $this->filterparams->logreader->get_events_select($selector, $params, $this->filterparams->orderby,
$this->get_page_start(), $this->get_page_size());
// Set initial bars.
if ($useinitialsbar && !$this->is_downloading()) {
$this->initialbars($total > $pagesize);
}
// Update list of users and courses list which will be displayed on log page.
$this->update_users_and_courses_used();
}
/**
* Helper function to create list of course shortname and user fullname shown in log report.
* This will update $this->userfullnames and $this->courseshortnames array with userfullname and courseshortname (with link),
* which will be used to render logs in table.
*/
public function update_users_and_courses_used() {
global $SITE, $DB;
$this->userfullnames = array();
$this->courseshortnames = array($SITE->id => $SITE->shortname);
$userids = array();
$courseids = array();
// For each event cache full username and course.
// Get list of userids and courseids which will be shown in log report.
foreach ($this->rawdata as $event) {
$logextra = $event->get_logextra();
if (!empty($event->userid) && !in_array($event->userid, $userids)) {
$userids[] = $event->userid;
}
if (!empty($logextra['realuserid']) && !in_array($logextra['realuserid'], $userids)) {
$userids[] = $logextra['realuserid'];
}
if (!empty($event->relateduserid) && !in_array($event->relateduserid, $userids)) {
$userids[] = $event->relateduserid;
}
if (!empty($event->courseid) && ($event->courseid != $SITE->id) && !in_array($event->courseid, $courseids)) {
$courseids[] = $event->courseid;
}
}
// Get user fullname and put that in return list.
if (!empty($userids)) {
list($usql, $uparams) = $DB->get_in_or_equal($userids);
$users = $DB->get_records_sql("SELECT id," . get_all_user_name_fields(true) . " FROM {user} WHERE id " . $usql,
$uparams);
foreach ($users as $userid => $user) {
$this->userfullnames[$userid] = fullname($user);
}
}
// Get course shortname and put that in return list.
if (!empty($courseids)) { // If all logs don't belog to site level then get course info.
list($coursesql, $courseparams) = $DB->get_in_or_equal($courseids);
$courses = $DB->get_records_sql("SELECT id,shortname FROM {course} WHERE id " . $coursesql, $courseparams);
foreach ($courses as $courseid => $course) {
$url = new moodle_url("/course/view.php", array('id' => $courseid));
$this->courseshortnames[$courseid] = html_writer::link($url, format_string($course->shortname));
}
}
}
}

View File

@ -28,20 +28,22 @@ require("../../config.php");
require_once("$CFG->libdir/graphlib.php");
require_once($CFG->dirroot.'/report/log/locallib.php');
$id = required_param('id', PARAM_INT); // Course ID
$type = required_param('type', PARAM_FILE); // Graph Type
$user = required_param('user', PARAM_INT); // Student ID
$date = optional_param('date', 0, PARAM_INT); // A time of a day (in GMT)
$id = required_param('id', PARAM_INT); // Course ID.
$type = required_param('type', PARAM_FILE); // Graph Type.
$user = required_param('user', PARAM_INT); // Student ID.
$date = optional_param('date', 0, PARAM_INT); // A time of a day (in GMT).
$logreader = optional_param('logreader', '', PARAM_COMPONENT);
$url = new moodle_url('/report/log/graph.php', array('id'=>$id,'type'=>$type,'user'=>$user,'date'=>$date));
$url = new moodle_url('/report/log/graph.php', array('id' => $id, 'type' => $type, 'user' => $user, 'date' => $date,
'logreader' => $logreader));
$PAGE->set_url($url);
if ($type !== "usercourse.png" and $type !== "userday.png") {
$type = 'userday.png';
}
$course = $DB->get_record("course", array("id"=>$id), '*', MUST_EXIST);
$user = $DB->get_record("user", array("id"=>$user, 'deleted'=>0), '*', MUST_EXIST);
$course = $DB->get_record("course", array("id" => $id), '*', MUST_EXIST);
$user = $DB->get_record("user", array("id" => $user, 'deleted' => 0), '*', MUST_EXIST);
$coursecontext = context_course::instance($course->id);
$personalcontext = context_user::instance($user->id);
@ -73,147 +75,150 @@ $timenow = time();
if ($type === "usercourse.png") {
$site = get_site();
$site = get_site();
if ($course->id == $site->id) {
$courseselect = 0;
} else {
$courseselect = $course->id;
}
if ($course->id == $site->id) {
$courseselect = 0;
} else {
$courseselect = $course->id;
}
$maxseconds = REPORT_LOG_MAX_DISPLAY * 3600 * 24; // seconds
//$maxseconds = 60 * 3600 * 24; // seconds
if ($timenow - $course->startdate > $maxseconds) {
$course->startdate = $timenow - $maxseconds;
}
$maxseconds = REPORT_LOG_MAX_DISPLAY * 3600 * 24; // Seconds.
if ($timenow - $course->startdate > $maxseconds) {
$course->startdate = $timenow - $maxseconds;
}
if (!empty($CFG->loglifetime)) {
$maxseconds = $CFG->loglifetime * 3600 * 24; // seconds
if ($timenow - $course->startdate > $maxseconds) {
$course->startdate = $timenow - $maxseconds;
}
}
if (!empty($CFG->loglifetime)) {
$maxseconds = $CFG->loglifetime * 3600 * 24; // Seconds.
if ($timenow - $course->startdate > $maxseconds) {
$course->startdate = $timenow - $maxseconds;
}
}
$timestart = $coursestart = usergetmidnight($course->startdate);
$timestart = $coursestart = usergetmidnight($course->startdate);
if ((($timenow - $timestart)/86400.0) > 40) {
$reducedays = 7;
} else {
$reducedays = 0;
}
if ((($timenow - $timestart) / 86400.0) > 40) {
$reducedays = 7;
} else {
$reducedays = 0;
}
$days = array();
$i = 0;
while ($timestart < $timenow) {
$timefinish = $timestart + 86400;
if ($reducedays) {
if ($i % $reducedays) {
$days[$i] = "";
} else {
$days[$i] = userdate($timestart, "%a %d %b");
}
} else {
$days[$i] = userdate($timestart, "%a %d %b");
}
$logs[$i] = 0;
$i++;
$timestart = $timefinish;
}
$days = array();
$i = 0;
while ($timestart < $timenow) {
$timefinish = $timestart + 86400;
if ($reducedays) {
if ($i % $reducedays) {
$days[$i] = "";
} else {
$days[$i] = userdate($timestart, "%a %d %b");
}
} else {
$days[$i] = userdate($timestart, "%a %d %b");
}
$logs[$i] = 0;
$i++;
$timestart = $timefinish;
}
if ($rawlogs = get_logs_usercourse($user->id, $courseselect, $coursestart)) {
foreach ($rawlogs as $rawlog) {
$logs[$rawlog->day] = $rawlog->num;
}
}
$rawlogs = report_log_usercourse($user->id, $courseselect, $coursestart);
$graph = new graph(750, 400);
if (empty($rawlogs)) {
return;
}
$a = new stdClass();
$a->coursename = format_string($course->shortname, true, array('context' => $coursecontext));
$a->username = fullname($user, true);
$graph->parameter['title'] = get_string("hitsoncourse", "", $a);
foreach ($rawlogs as $rawlog) {
$logs[$rawlog->day] = $rawlog->num;
}
$graph->x_data = $days;
$graph = new graph(750, 400);
$graph->y_data['logs'] = $logs;
$graph->y_order = array('logs');
$a = new stdClass();
$a->coursename = format_string($course->shortname, true, array('context' => $coursecontext));
$a->username = fullname($user, true);
$graph->parameter['title'] = get_string("hitsoncourse", "", $a);
if (!empty($CFG->preferlinegraphs)) {
$graph->y_format['logs'] = array('colour' => 'blue','line' => 'line');
} else {
$graph->y_format['logs'] = array('colour' => 'blue','bar' => 'fill','bar_size' => 0.6);
$graph->parameter['bar_spacing'] = 0;
}
$graph->x_data = $days;
$graph->y_data['logs'] = $logs;
$graph->y_order = array('logs');
if (!empty($CFG->preferlinegraphs)) {
$graph->y_format['logs'] = array('colour' => 'blue', 'line' => 'line');
} else {
$graph->y_format['logs'] = array('colour' => 'blue', 'bar' => 'fill', 'bar_size' => 0.6);
$graph->parameter['bar_spacing'] = 0;
}
$graph->parameter['y_label_left'] = get_string("hits");
$graph->parameter['label_size'] = "12";
$graph->parameter['x_axis_angle'] = 90;
$graph->parameter['x_label_angle'] = 0;
$graph->parameter['tick_length'] = 0;
$graph->parameter['y_label_left'] = get_string("hits");
$graph->parameter['label_size'] = "12";
$graph->parameter['x_axis_angle'] = 90;
$graph->parameter['x_label_angle'] = 0;
$graph->parameter['tick_length'] = 0;
$graph->parameter['shadow'] = 'none';
$graph->parameter['shadow'] = 'none';
error_reporting(5); // ignore most warnings such as font problems etc
$graph->draw_stack();
error_reporting(5); // Ignore most warnings such as font problems etc.
$graph->draw_stack();
} else {
$site = get_site();
$site = get_site();
if ($course->id == $site->id) {
$courseselect = 0;
} else {
$courseselect = $course->id;
}
if ($course->id == $site->id) {
$courseselect = 0;
} else {
$courseselect = $course->id;
}
if ($date) {
$daystart = usergetmidnight($date);
} else {
$daystart = usergetmidnight(time());
}
$dayfinish = $daystart + 86400;
if ($date) {
$daystart = usergetmidnight($date);
} else {
$daystart = usergetmidnight(time());
}
$dayfinish = $daystart + 86400;
$hours = array();
for ($i=0; $i<=23; $i++) {
$logs[$i] = 0;
$hour = $daystart + $i * 3600;
$hours[$i] = $i;
}
$hours = array();
for ($i = 0; $i <= 23; $i++) {
$logs[$i] = 0;
$hour = $daystart + $i * 3600;
$hours[$i] = $i;
}
if ($rawlogs = get_logs_userday($user->id, $courseselect, $daystart)) {
foreach ($rawlogs as $rawlog) {
$logs[$rawlog->hour] = $rawlog->num;
}
}
$rawlogs = report_log_userday($user->id, $courseselect, $daystart);
$graph = new graph(750, 400);
if (empty($rawlogs)) {
return;
}
$a = new stdClass();
$a->coursename = format_string($course->shortname, true, array('context' => $coursecontext));
$a->username = fullname($user, true);
$graph->parameter['title'] = get_string("hitsoncoursetoday", "", $a);
foreach ($rawlogs as $rawlog) {
$logs[$rawlog->hour] = $rawlog->num;
}
$graph->x_data = $hours;
$graph = new graph(750, 400);
$graph->y_data['logs'] = $logs;
$graph->y_order = array('logs');
$a = new stdClass();
$a->coursename = format_string($course->shortname, true, array('context' => $coursecontext));
$a->username = fullname($user, true);
if (!empty($CFG->preferlinegraphs)) {
$graph->y_format['logs'] = array('colour' => 'blue','line' => 'line');
} else {
$graph->y_format['logs'] = array('colour' => 'blue','bar' => 'fill','bar_size' => 0.9);
}
$graph->parameter['title'] = get_string("hitsoncoursetoday", "", $a);
$graph->x_data = $hours;
$graph->y_data['logs'] = $logs;
$graph->y_order = array('logs');
$graph->parameter['y_label_left'] = get_string("hits");
$graph->parameter['label_size'] = "12";
$graph->parameter['x_axis_angle'] = 0;
$graph->parameter['x_label_angle'] = 0;
if (!empty($CFG->preferlinegraphs)) {
$graph->y_format['logs'] = array('colour' => 'blue', 'line' => 'line');
} else {
$graph->y_format['logs'] = array('colour' => 'blue', 'bar' => 'fill', 'bar_size' => 0.9);
}
$graph->parameter['shadow'] = 'none';
$graph->parameter['y_label_left'] = get_string("hits");
$graph->parameter['label_size'] = "12";
$graph->parameter['x_axis_angle'] = 0;
$graph->parameter['x_label_angle'] = 0;
$graph->parameter['shadow'] = 'none';
error_reporting(5); // ignore most warnings such as font problems etc
$graph->draw_stack();
error_reporting(5); // Ignore most warnings such as font problems etc.
$graph->draw_stack();
}

View File

@ -26,40 +26,24 @@ require('../../config.php');
require_once($CFG->dirroot.'/course/lib.php');
require_once($CFG->dirroot.'/report/log/locallib.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/lib/tablelib.php');
$id = optional_param('id', 0, PARAM_INT);// Course ID
$host_course = optional_param('host_course', '', PARAM_PATH);// Course ID
if (empty($host_course)) {
$hostid = $CFG->mnet_localhost_id;
if (empty($id)) {
$site = get_site();
$id = $site->id;
}
} else {
list($hostid, $id) = explode('/', $host_course);
}
$group = optional_param('group', 0, PARAM_INT); // Group to display
$user = optional_param('user', 0, PARAM_INT); // User to display
$date = optional_param('date', 0, PARAM_INT); // Date to display
$modname = optional_param('modname', '', PARAM_PLUGIN); // course_module->id
$modid = optional_param('modid', 0, PARAM_FILE); // number or 'site_errors'
$modaction = optional_param('modaction', '', PARAM_PATH); // an action as recorded in the logs
$page = optional_param('page', '0', PARAM_INT); // which page to show
$perpage = optional_param('perpage', '100', PARAM_INT); // how many per page
$showcourses = optional_param('showcourses', 0, PARAM_INT); // whether to show courses if we're over our limit.
$showusers = optional_param('showusers', 0, PARAM_INT); // whether to show users if we're over our limit.
$chooselog = optional_param('chooselog', 0, PARAM_INT);
$logformat = optional_param('logformat', 'showashtml', PARAM_ALPHA);
$id = optional_param('id', 0, PARAM_INT);// Course ID.
$group = optional_param('group', 0, PARAM_INT); // Group to display.
$user = optional_param('user', 0, PARAM_INT); // User to display.
$date = optional_param('date', 0, PARAM_INT); // Date to display.
$modid = optional_param('modid', 0, PARAM_ALPHANUMEXT); // Module id or 'site_errors'.
$modaction = optional_param('modaction', '', PARAM_ALPHAEXT); // An action as recorded in the logs.
$page = optional_param('page', '0', PARAM_INT); // Which page to show.
$perpage = optional_param('perpage', '100', PARAM_INT); // How many per page.
$showcourses = optional_param('showcourses', false, PARAM_BOOL); // Whether to show courses if we're over our limit.
$showusers = optional_param('showusers', false, PARAM_BOOL); // Whether to show users if we're over our limit.
$chooselog = optional_param('chooselog', false, PARAM_BOOL);
$logformat = optional_param('download', '', PARAM_ALPHA);
$logreader = optional_param('logreader', '', PARAM_COMPONENT); // Reader which will be used for displaying logs.
$edulevel = optional_param('edulevel', -1, PARAM_INT); // Educational level.
$params = array();
if ($id !== 0) {
$params['id'] = $id;
}
if ($host_course !== '') {
$params['host_course'] = $host_course;
}
if ($group !== 0) {
$params['group'] = $group;
}
@ -69,9 +53,6 @@ if ($user !== 0) {
if ($date !== 0) {
$params['date'] = $date;
}
if ($modname !== '') {
$params['modname'] = $modname;
}
if ($modid !== 0) {
$params['modid'] = $modid;
}
@ -84,45 +65,60 @@ if ($page !== '0') {
if ($perpage !== '100') {
$params['perpage'] = $perpage;
}
if ($showcourses !== 0) {
if ($showcourses) {
$params['showcourses'] = $showcourses;
}
if ($showusers !== 0) {
if ($showusers) {
$params['showusers'] = $showusers;
}
if ($chooselog !== 0) {
if ($chooselog) {
$params['chooselog'] = $chooselog;
}
if ($logformat !== 'showashtml') {
$params['logformat'] = $logformat;
if ($logformat !== '') {
$params['download'] = $logformat;
}
$PAGE->set_url('/report/log/index.php', $params);
if ($logreader !== '') {
$params['logreader'] = $logreader;
}
if (($edulevel != -1)) {
$params['edulevel'] = $edulevel;
}
// Legacy store hack, as edulevel is not supported.
if ($logreader == 'logstore_legacy') {
$params['edulevel'] = -1;
$edulevel = -1;
}
$url = new moodle_url("/report/log/index.php", $params);
$PAGE->set_url('/report/log/index.php', array('id' => $id));
$PAGE->set_pagelayout('report');
if ($hostid == $CFG->mnet_localhost_id) {
$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST);
// Get course details.
$course = null;
if ($id) {
$course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);
require_login($course);
$context = context_course::instance($course->id);
} else {
$course_stub = $DB->get_record('mnet_log', array('hostid'=>$hostid, 'course'=>$id), '*', true);
$course->id = $id;
$course->shortname = $course_stub->coursename;
$course->fullname = $course_stub->coursename;
require_login();
$context = context_system::instance();
$PAGE->set_context($context);
}
require_login($course);
$context = context_course::instance($course->id);
require_capability('report/log:view', $context);
// Trigger a report viewed event.
$event = \report_log\event\report_viewed::create(array('context' => $context, 'relateduserid' => $user,
'other' => array('groupid' => $group, 'date' => $date, 'modid' => $modid, 'modaction' => $modaction,
'logformat' => $logformat)));
$event->trigger();
// When user choose to view logs then only trigger event.
if ($chooselog) {
// Trigger a report viewed event.
$event = \report_log\event\report_viewed::create(array('context' => $context, 'relateduserid' => $user,
'other' => array('groupid' => $group, 'date' => $date, 'modid' => $modid, 'modaction' => $modaction,
'logformat' => $logformat)));
$event->trigger();
}
if (!empty($page)) {
$strlogs = get_string('logs'). ": ". get_string('page', 'report_log', $page+1);
$strlogs = get_string('logs'). ": ". get_string('page', 'report_log', $page + 1);
} else {
$strlogs = get_string('logs');
}
@ -134,83 +130,55 @@ $adminediting = optional_param('adminedit', -1, PARAM_BOOL);
if ($PAGE->user_allowed_editing() && $adminediting != -1) {
$USER->editing = $adminediting;
}
\core\session\manager::write_close();
if (!empty($chooselog)) {
$userinfo = get_string('allparticipants');
$dateinfo = get_string('alldays');
if ($user) {
$u = $DB->get_record('user', array('id'=>$user, 'deleted'=>0), '*', MUST_EXIST);
$userinfo = fullname($u, has_capability('moodle/site:viewfullnames', $context));
}
if ($date) {
$dateinfo = userdate($date, get_string('strftimedaydate'));
}
switch ($logformat) {
case 'showashtml':
if ($hostid != $CFG->mnet_localhost_id || $course->id == SITEID) {
admin_externalpage_setup('reportlog');
$PAGE->set_title($course->shortname .': '. $strlogs);
echo $OUTPUT->header();
} else {
$PAGE->set_title($course->shortname .': '. $strlogs);
$PAGE->set_heading($course->fullname);
$PAGE->navbar->add("$userinfo, $dateinfo");
echo $OUTPUT->header();
}
echo $OUTPUT->heading(format_string($course->fullname) . ": $userinfo, $dateinfo (".usertimezone().")");
report_log_print_mnet_selector_form($hostid, $course, $user, $date, $modname, $modid, $modaction, $group, $showcourses, $showusers, $logformat);
if ($hostid == $CFG->mnet_localhost_id) {
print_log($course, $user, $date, 'l.time DESC', $page, $perpage,
"index.php?id=$course->id&amp;chooselog=1&amp;user=$user&amp;date=$date&amp;modid=$modid&amp;modaction=$modaction&amp;group=$group",
$modname, $modid, $modaction, $group);
} else {
print_mnet_log($hostid, $id, $user, $date, 'l.time DESC', $page, $perpage, "", $modname, $modid, $modaction, $group);
}
break;
case 'downloadascsv':
if (!print_log_csv($course, $user, $date, 'l.time DESC', $modname,
$modid, $modaction, $group)) {
echo $OUTPUT->notification("No logs found!");
echo $OUTPUT->footer();
}
exit;
case 'downloadasods':
if (!print_log_ods($course, $user, $date, 'l.time DESC', $modname,
$modid, $modaction, $group)) {
echo $OUTPUT->notification("No logs found!");
echo $OUTPUT->footer();
}
exit;
case 'downloadasexcel':
if (!print_log_xls($course, $user, $date, 'l.time DESC', $modname,
$modid, $modaction, $group)) {
echo $OUTPUT->notification("No logs found!");
echo $OUTPUT->footer();
}
exit;
}
if (empty($course) || ($course->id == $SITE->id)) {
admin_externalpage_setup('reportlog', '', null, '', array('pagelayout' => 'report'));
$PAGE->set_title($SITE->shortname .': '. $strlogs);
} else {
if ($hostid != $CFG->mnet_localhost_id || $course->id == SITEID) {
admin_externalpage_setup('reportlog', '', null, '', array('pagelayout'=>'report'));
echo $OUTPUT->header();
} else {
$PAGE->set_title($course->shortname .': '. $strlogs);
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
}
echo $OUTPUT->heading(get_string('chooselogs') .':');
report_log_print_selector_form($course, $user, $date, $modname, $modid, $modaction, $group, $showcourses, $showusers, $logformat);
$PAGE->set_title($course->shortname .': '. $strlogs);
$PAGE->set_heading($course->fullname);
}
echo $OUTPUT->footer();
$reportlog = new report_log_renderable($logreader, $course, $user, $modid, $modaction, $group, $edulevel, $showcourses, $showusers,
$chooselog, true, $url, $date, $logformat, $page, $perpage, 'timecreated DESC');
$readers = $reportlog->get_readers();
$output = $PAGE->get_renderer('report_log');
if (empty($readers)) {
echo $output->header();
echo $output->heading(get_string('noreaderenabled'));
} else {
if (!empty($chooselog)) {
// Delay creation of table, till called by user with filter.
$reportlog->setup_table();
if (empty($logformat)) {
echo $output->header();
$userinfo = get_string('allparticipants');
$dateinfo = get_string('alldays');
if ($user) {
$u = $DB->get_record('user', array('id' => $user, 'deleted' => 0), '*', MUST_EXIST);
$userinfo = fullname($u, has_capability('moodle/site:viewfullnames', $context));
}
if ($date) {
$dateinfo = userdate($date, get_string('strftimedaydate'));
}
if (!empty($course) && ($course->id != SITEID)) {
$PAGE->navbar->add("$userinfo, $dateinfo");
}
echo $output->render($reportlog);
} else {
$reportlog->download();
exit();
}
} else {
echo $output->header();
echo $output->heading(get_string('chooselogs') .':');
echo $output->render($reportlog);
}
}
echo $output->footer();

View File

@ -24,13 +24,20 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['eventcomponent'] = 'Component';
$string['eventcontext'] = 'Event context';
$string['eventloggedas'] = '{$a->realusername} as {$a->asusername}';
$string['eventorigin'] = 'Origin';
$string['eventrelatedfullnameuser'] = 'Affected user';
$string['eventreportviewed'] = 'Log report viewed';
$string['eventuserreportviewed'] = 'User log report viewed';
$string['log:view'] = 'View course logs';
$string['log:viewtoday'] = 'View today\'s logs';
$string['page'] = 'Page {$a}';
$string['logsformat'] = 'Logs format';
$string['nologreaderenabled'] = 'No log reader enabled';
$string['page-report-log-x'] = 'Any log report';
$string['page-report-log-index'] = 'Course log report';
$string['page-report-log-user'] = 'User course log report';
$string['pluginname'] = 'Logs';
$string['selectlogreader'] = 'Select log reader';

View File

@ -40,14 +40,127 @@ require_once(dirname(__FILE__).'/lib.php');
* @param int $userid id of the user whose logs are needed
* @param string $type type of logs graph needed (usercourse.png/userday.png)
* @param int $date timestamp in GMT (seconds since epoch)
* @param string $logreader Log reader.
* @return void
*/
function report_log_print_graph($course, $userid, $type, $date=0) {
global $CFG;
function report_log_print_graph($course, $userid, $type, $date=0, $logreader='') {
// If reader is not a sql_reader and not legacy store then don't show graph.
$logmanager = get_log_manager();
$readers = $logmanager->get_readers();
echo '<img src="'.$CFG->wwwroot.'/report/log/graph.php?id='.$course->id.
'&amp;user='.$userid.'&amp;type='.$type.'&amp;date='.$date.'" alt="" />';
if (empty($logreader)) {
$reader = reset($readers);
} else {
$reader = $readers[$logreader];
}
if (!($reader instanceof core\log\sql_select_reader)) {
return;
}
$url = new moodle_url('/report/log/graph.php', array('id' => $course->id, 'user' => $userid, 'type' => $type,
'date' => $date, 'logreader' => $logreader));
echo html_writer::empty_tag('img', array('src' => $url, 'alt' => ''));
}
/**
* Select all log records for a given course and user
*
* @param int $userid The id of the user as found in the 'user' table.
* @param int $courseid The id of the course as found in the 'course' table.
* @param string $coursestart unix timestamp representing course start date and time.
* @param string $logreader log reader to use.
* @return array
*/
function report_log_usercourse($userid, $courseid, $coursestart, $logreader = '') {
global $DB;
$logmanager = get_log_manager();
$readers = $logmanager->get_readers();
if (empty($logreader)) {
$reader = reset($readers);
} else {
$reader = $readers[$logreader];
}
// If reader is not a sql_reader and not legacy store then return.
if (!($reader instanceof \core\log\sql_reader) && !($reader instanceof logstore_legacy\log\store)) {
return array();
}
$coursestart = (int)$coursestart; // Note: unfortunately pg complains if you use name parameter or column alias in GROUP BY.
if ($reader instanceof logstore_legacy\log\store) {
$logtable = 'log';
$timefield = 'time';
$coursefield = 'course';
} else {
$logtable = $reader->get_log_table();
$timefield = 'timecreated';
$coursefield = 'courseid';
}
$params = array();
$courseselect = '';
if ($courseid) {
$courseselect = "AND $coursefield = :courseid";
$params['courseid'] = $courseid;
}
$params['userid'] = $userid;
return $DB->get_records_sql("SELECT FLOOR(($timefield - $coursestart)/" . DAYSECS . ") AS day, COUNT(*) AS num
FROM {" . $logtable . "}
WHERE userid = :userid
AND $timefield > $coursestart $courseselect
GROUP BY FLOOR(($timefield - $coursestart)/" . DAYSECS .")", $params);
}
/**
* Select all log records for a given course, user, and day
*
* @param int $userid The id of the user as found in the 'user' table.
* @param int $courseid The id of the course as found in the 'course' table.
* @param string $daystart unix timestamp of the start of the day for which the logs needs to be retrived
* @param string $logreader log reader to use.
* @return array
*/
function report_log_userday($userid, $courseid, $daystart, $logreader = '') {
global $DB;
$logmanager = get_log_manager();
$readers = $logmanager->get_readers();
if (empty($logreader)) {
$reader = reset($readers);
} else {
$reader = $readers[$logreader];
}
// If reader is not a sql_reader and not legacy store then return.
if (!($reader instanceof \core\log\sql_reader) && !($reader instanceof logstore_legacy\log\store)) {
return array();
}
$daystart = (int)$daystart; // Note: unfortunately pg complains if you use name parameter or column alias in GROUP BY.
if ($reader instanceof logstore_legacy\log\store) {
$logtable = 'log';
$timefield = 'time';
$coursefield = 'course';
} else {
$logtable = $reader->get_log_table();
$timefield = 'timecreated';
$coursefield = 'courseid';
}
$params = array('userid' => $userid);
$courseselect = '';
if ($courseid) {
$courseselect = "AND $coursefield = :courseid";
$params['courseid'] = $courseid;
}
return $DB->get_records_sql("SELECT FLOOR(($timefield - $daystart)/" . HOURSECS . ") AS hour, COUNT(*) AS num
FROM {" . $logtable . "}
WHERE userid = :userid
AND $timefield > $daystart $courseselect
GROUP BY FLOOR(($timefield - $daystart)/" . HOURSECS . ") ", $params);
}
/**
* This function is used to generate and display Mnet selector form
*
@ -381,264 +494,3 @@ function report_log_print_mnet_selector_form($hostid, $course, $selecteduser=0,
echo '</div>';
echo '</form>';
}
/**
* This function is used to generate and display selector form
*
* @global stdClass $USER
* @global stdClass $CFG
* @global moodle_database $DB
* @global core_renderer $OUTPUT
* @global stdClass $SESSION
* @uses CONTEXT_SYSTEM
* @uses COURSE_MAX_COURSES_PER_DROPDOWN
* @uses CONTEXT_COURSE
* @uses SEPARATEGROUPS
* @param stdClass $course course instance
* @param int $selecteduser id of the selected user
* @param string $selecteddate Date selected
* @param string $modname course_module->id
* @param string $modid number or 'site_errors'
* @param string $modaction an action as recorded in the logs
* @param int $selectedgroup Group to display
* @param int $showcourses whether to show courses if we're over our limit.
* @param int $showusers whether to show users if we're over our limit.
* @param string $logformat Format of the logs (downloadascsv, showashtml, downloadasods, downloadasexcel)
* @return void
*/
function report_log_print_selector_form($course, $selecteduser=0, $selecteddate='today',
$modname="", $modid=0, $modaction='', $selectedgroup=-1, $showcourses=0, $showusers=0, $logformat='showashtml') {
global $USER, $CFG, $DB, $OUTPUT, $SESSION;
// first check to see if we can override showcourses and showusers
$numcourses = $DB->count_records("course");
if ($numcourses < COURSE_MAX_COURSES_PER_DROPDOWN && !$showcourses) {
$showcourses = 1;
}
$sitecontext = context_system::instance();
$context = context_course::instance($course->id);
/// Setup for group handling.
if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
$selectedgroup = -1;
$showgroups = false;
} else if ($course->groupmode) {
$showgroups = true;
} else {
$selectedgroup = 0;
$showgroups = false;
}
if ($selectedgroup === -1) {
if (isset($SESSION->currentgroup[$course->id])) {
$selectedgroup = $SESSION->currentgroup[$course->id];
} else {
$selectedgroup = groups_get_all_groups($course->id, $USER->id);
if (is_array($selectedgroup)) {
$selectedgroup = array_shift(array_keys($selectedgroup));
$SESSION->currentgroup[$course->id] = $selectedgroup;
} else {
$selectedgroup = 0;
}
}
}
// Get all the possible users
$users = array();
// Define limitfrom and limitnum for queries below
// If $showusers is enabled... don't apply limitfrom and limitnum
$limitfrom = empty($showusers) ? 0 : '';
$limitnum = empty($showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : '';
$courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, ' . get_all_user_name_fields(true, 'u'),
null, $limitfrom, $limitnum);
if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$showusers) {
$showusers = 1;
}
if ($showusers) {
if ($courseusers) {
foreach ($courseusers as $courseuser) {
$users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context));
}
}
$users[$CFG->siteguest] = get_string('guestuser');
}
if (has_capability('report/log:view', $sitecontext) && $showcourses) {
if ($ccc = $DB->get_records("course", null, "fullname", "id,shortname,fullname,category")) {
foreach ($ccc as $cc) {
if ($cc->category) {
$courses["$cc->id"] = format_string(get_course_display_name_for_list($cc));
} else {
$courses["$cc->id"] = format_string($cc->fullname) . ' (Site)';
}
}
}
asort($courses);
}
$activities = array();
$selectedactivity = "";
$modinfo = get_fast_modinfo($course);
if (!empty($modinfo->cms)) {
$section = 0;
$thissection = array();
foreach ($modinfo->cms as $cm) {
if (!$cm->uservisible || !$cm->has_view()) {
continue;
}
if ($cm->sectionnum > 0 and $section <> $cm->sectionnum) {
$activities[] = $thissection;
$thissection = array();
}
$section = $cm->sectionnum;
$modname = strip_tags($cm->get_formatted_name());
if (core_text::strlen($modname) > 55) {
$modname = core_text::substr($modname, 0, 50)."...";
}
if (!$cm->visible) {
$modname = "(".$modname.")";
}
$key = get_section_name($course, $cm->sectionnum);
if (!isset($thissection[$key])) {
$thissection[$key] = array();
}
$thissection[$key][$cm->id] = $modname;
if ($cm->id == $modid) {
$selectedactivity = "$cm->id";
}
}
if (!empty($thissection)) {
$activities[] = $thissection;
}
}
if (has_capability('report/log:view', $sitecontext) && ($course->id == SITEID)) {
$activities["site_errors"] = get_string("siteerrors");
if ($modid === "site_errors") {
$selectedactivity = "site_errors";
}
}
$strftimedate = get_string("strftimedate");
$strftimedaydate = get_string("strftimedaydate");
asort($users);
// Prepare the list of action options.
$actions = array(
'view' => get_string('view'),
'add' => get_string('add'),
'update' => get_string('update'),
'delete' => get_string('delete'),
'-view' => get_string('allchanges')
);
// Get all the possible dates
// Note that we are keeping track of real (GMT) time and user time
// User time is only used in displays - all calcs and passing is GMT
$timenow = time(); // GMT
// What day is it now for the user, and when is midnight that day (in GMT).
$timemidnight = $today = usergetmidnight($timenow);
// Put today up the top of the list
$dates = array("$timemidnight" => get_string("today").", ".userdate($timenow, $strftimedate) );
if (!$course->startdate or ($course->startdate > $timenow)) {
$course->startdate = $course->timecreated;
}
$numdates = 1;
while ($timemidnight > $course->startdate and $numdates < 365) {
$timemidnight = $timemidnight - 86400;
$timenow = $timenow - 86400;
$dates["$timemidnight"] = userdate($timenow, $strftimedaydate);
$numdates++;
}
if ($selecteddate == "today") {
$selecteddate = $today;
}
echo "<form class=\"logselectform\" action=\"$CFG->wwwroot/report/log/index.php\" method=\"get\">\n";
echo "<div>\n";
echo "<input type=\"hidden\" name=\"chooselog\" value=\"1\" />\n";
echo "<input type=\"hidden\" name=\"showusers\" value=\"$showusers\" />\n";
echo "<input type=\"hidden\" name=\"showcourses\" value=\"$showcourses\" />\n";
if (has_capability('report/log:view', $sitecontext) && $showcourses) {
echo html_writer::label(get_string('selectacourse'), 'menuid', false, array('class' => 'accesshide'));
echo html_writer::select($courses, "id", $course->id, false);
} else {
// echo '<input type="hidden" name="id" value="'.$course->id.'" />';
$courses = array();
$courses[$course->id] = get_course_display_name_for_list($course) . (($course->id == SITEID) ? ' ('.get_string('site').') ' : '');
echo html_writer::label(get_string('selectacourse'), 'menuid', false, array('class' => 'accesshide'));
echo html_writer::select($courses,"id",$course->id, false);
if (has_capability('report/log:view', $sitecontext)) {
$a = new stdClass();
$a->url = "$CFG->wwwroot/report/log/index.php?chooselog=0&group=$selectedgroup&user=$selecteduser"
."&id=$course->id&date=$selecteddate&modid=$selectedactivity&showcourses=1&showusers=$showusers";
print_string('logtoomanycourses','moodle',$a);
}
}
if ($showgroups) {
if ($cgroups = groups_get_all_groups($course->id)) {
foreach ($cgroups as $cgroup) {
$groups[$cgroup->id] = $cgroup->name;
}
}
else {
$groups = array();
}
echo html_writer::label(get_string('selectagroup'), 'menugroup', false, array('class' => 'accesshide'));
echo html_writer::select($groups, "group", $selectedgroup, get_string("allgroups"));
}
if ($showusers) {
echo html_writer::label(get_string('selctauser'), 'menuuser', false, array('class' => 'accesshide'));
echo html_writer::select($users, "user", $selecteduser, get_string("allparticipants"));
}
else {
$users = array();
if (!empty($selecteduser)) {
$user = $DB->get_record('user', array('id'=>$selecteduser));
$users[$selecteduser] = fullname($user);
}
else {
$users[0] = get_string('allparticipants');
}
echo html_writer::label(get_string('selctauser'), 'menuuser', false, array('class' => 'accesshide'));
echo html_writer::select($users, "user", $selecteduser, false);
$a = new stdClass();
$a->url = "$CFG->wwwroot/report/log/index.php?chooselog=0&group=$selectedgroup&user=$selecteduser"
."&id=$course->id&date=$selecteddate&modid=$selectedactivity&showusers=1&showcourses=$showcourses";
print_string('logtoomanyusers','moodle',$a);
}
echo html_writer::label(get_string('date'), 'menudate', false, array('class' => 'accesshide'));
echo html_writer::select($dates, "date", $selecteddate, get_string("alldays"));
echo html_writer::label(get_string('activities'), 'menumodid', false, array('class' => 'accesshide'));
echo html_writer::select($activities, "modid", $selectedactivity, get_string("allactivities"));
echo html_writer::label(get_string('actions'), 'menumodaction', false, array('class' => 'accesshide'));
echo html_writer::select($actions, 'modaction', $modaction, get_string("allactions"));
$logformats = array('showashtml' => get_string('displayonpage'),
'downloadascsv' => get_string('downloadtext'),
'downloadasods' => get_string('downloadods'),
'downloadasexcel' => get_string('downloadexcel'));
echo html_writer::label(get_string('logsformat', 'report_log'), 'menulogformat', false, array('class' => 'accesshide'));
echo html_writer::select($logformats, 'logformat', $logformat, false);
echo '<input type="submit" value="'.get_string('gettheselogs').'" />';
echo '</div>';
echo '</form>';
}

View File

@ -26,8 +26,9 @@
defined('MOODLE_INTERNAL') || die;
// just a link to course report
$ADMIN->add('reports', new admin_externalpage('reportlog', get_string('log', 'admin'), "$CFG->wwwroot/report/log/index.php?id=".SITEID, 'report/log:view'));
// Just a link to course report.
$ADMIN->add('reports', new admin_externalpage('reportlog', get_string('log', 'admin'),
$CFG->wwwroot . "/report/log/index.php?id=0", 'report/log:view'));
// no report settings
// No report settings.
$settings = null;

View File

@ -24,19 +24,21 @@
require('../../config.php');
require_once($CFG->dirroot.'/report/log/locallib.php');
require_once($CFG->dirroot.'/lib/tablelib.php');
$userid = required_param('id', PARAM_INT);
$courseid = required_param('course', PARAM_INT);
$mode = optional_param('mode', 'today', PARAM_ALPHA);
$page = optional_param('page', 0, PARAM_INT);
$perpage = optional_param('perpage', 100, PARAM_INT);
$logreader = optional_param('logreader', '', PARAM_COMPONENT); // Log reader which will be used for displaying logs.
if ($mode !== 'today' and $mode !== 'all') {
$mode = 'today';
}
$user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
$user = $DB->get_record('user', array('id' => $userid, 'deleted' => 0), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
$coursecontext = context_course::instance($course->id);
$personalcontext = context_user::instance($user->id);
@ -65,7 +67,7 @@ if ($mode === 'today') {
$stractivityreport = get_string('activityreport');
$PAGE->set_pagelayout('report');
$PAGE->set_url('/report/log/user.php', array('id'=>$user->id, 'course'=>$course->id, 'mode'=>$mode));
$PAGE->set_url('/report/log/user.php', array('id' => $user->id, 'course' => $course->id, 'mode' => $mode));
$PAGE->navigation->extend_for_user($user);
$PAGE->navigation->set_userid_for_parent_checks($user->id); // see MDL-25805 for reasons and for full commit reference for reversal when fixed.
$PAGE->set_title("$course->shortname: $stractivityreport");
@ -78,18 +80,24 @@ $event->trigger();
echo $OUTPUT->header();
$output = $PAGE->get_renderer('report_log');
$reportlog = new report_log_renderable($logreader, $course, $user->id, 0, '', -1, -1, false, false, true, false, $PAGE->url,
usergetmidnight(time()), '', $page, $perpage, 'timecreated DESC');
$reportlog->setup_table();
$reportlog->tablelog->is_downloadable(false);
echo $output->reader_selector($reportlog);
if ($mode === 'today') {
echo '<div class="graph">';
report_log_print_graph($course, $user->id, "userday.png");
report_log_print_graph($course, $user->id, "userday.png", 0, $logreader);
echo '</div>';
print_log($course, $user->id, usergetmidnight(time()), "l.time DESC", $page, $perpage,
"user.php?course=$course->id&amp;id=$user->id&amp;mode=$mode");
echo $output->render($reportlog);
} else {
echo '<div class="graph">';
report_log_print_graph($course, $user->id, "usercourse.png");
report_log_print_graph($course, $user->id, "usercourse.png", 0, $logreader);
echo '</div>';
print_log($course, $user->id, 0, "l.time DESC", $page, $perpage,
"user.php?course=$course->id&amp;id=$user->id&amp;mode=$mode");
$reportlog->selecteddate = 0;
echo $output->render($reportlog);
}
echo $OUTPUT->footer();

View File

@ -26,6 +26,6 @@
defined('MOODLE_INTERNAL') || die;
$plugin->version = 2013110500; // The current plugin version (Date: YYYYMMDDXX)
$plugin->version = 2014031800; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2013110500; // Requires this Moodle version
$plugin->component = 'report_log'; // Full name of the plugin (used for diagnostics)