Commit 70279746 authored by Mark Nelson's avatar Mark Nelson
Browse files

MDL-41286 report_outline: updated report to use logging api

AMOS START
 MOV [neverseen, mod_folder],[neverseen, report_outline]
 MOV [neverseen, mod_page],[neverseen, report_outline]
 MOV [neverseen, mod_resource],[neverseen, report_outline]
 MOV [neverseen, mod_url],[neverseen, report_outline]
AMOS END
parent 63eb19cb
......@@ -112,47 +112,6 @@ function book_delete_instance($id) {
return true;
}
/**
* Return use outline
*
* @param stdClass $course
* @param stdClass $user
* @param stdClass $mod
* @param object $book
* @return object|null
*/
function book_user_outline($course, $user, $mod, $book) {
global $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'book',
'action'=>'view', 'info'=>$book->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$result = new stdClass();
$result->info = get_string('numviews', '', $numviews);
$result->time = $lastlog->time;
return $result;
}
return null;
}
/**
* Print a detailed representation of what a user has done with
* a given particular instance of this module, for user activity reports.
*
* @param stdClass $course
* @param stdClass $user
* @param stdClass $mod
* @param stdClass $book
* @return bool
*/
function book_user_complete($course, $user, $mod, $book) {
return true;
}
/**
* Given a course and a time, this module should find recent activity
* that has occurred in book activities and print it out.
......
......@@ -203,39 +203,6 @@ function chat_delete_instance($id) {
return $result;
}
/**
* Return a small object with summary information about what a
* user has done with a given particular instance of this module
* Used for user activity reports.
* <code>
* $return->time = the time they did it
* $return->info = a short text description
* </code>
*
* @param object $course
* @param object $user
* @param object $mod
* @param object $chat
* @return void
*/
function chat_user_outline($course, $user, $mod, $chat) {
return NULL;
}
/**
* Print a detailed representation of what a user has done with
* a given particular instance of this module, for user activity reports.
*
* @param object $course
* @param object $user
* @param object $mod
* @param object $chat
* @return bool
*/
function chat_user_complete($course, $user, $mod, $chat) {
return true;
}
/**
* Given a course and a date, prints a summary of all chat rooms past and present
* This function is called from block_recent_activity
......
......@@ -39,7 +39,6 @@ A folder may be used
* To provide a shared uploading space for teachers on the course page (keeping the folder hidden so that only teachers can see it)';
$string['modulename_link'] = 'mod/folder/view';
$string['modulenameplural'] = 'Folders';
$string['neverseen'] = 'Never seen';
$string['page-mod-folder-x'] = 'Any folder module page';
$string['page-mod-folder-view'] = 'Folder module main page';
$string['pluginadministration'] = 'Folder administration';
......
......@@ -168,57 +168,6 @@ function folder_delete_instance($id) {
return true;
}
/**
* Return use outline
* @param object $course
* @param object $user
* @param object $mod
* @param object $folder
* @return object|null
*/
function folder_user_outline($course, $user, $mod, $folder) {
global $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'folder',
'action'=>'view', 'info'=>$folder->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$result = new stdClass();
$result->info = get_string('numviews', '', $numviews);
$result->time = $lastlog->time;
return $result;
}
return NULL;
}
/**
* Return use complete
* @param object $course
* @param object $user
* @param object $mod
* @param object $folder
*/
function folder_user_complete($course, $user, $mod, $folder) {
global $CFG, $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'folder',
'action'=>'view', 'info'=>$folder->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$strmostrecently = get_string('mostrecently');
$strnumviews = get_string('numviews', '', $numviews);
echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
} else {
print_string('neverseen', 'folder');
}
}
/**
* Lists all browsable file areas
*
......
......@@ -219,57 +219,6 @@ function imscp_delete_instance($id) {
return true;
}
/**
* Return use outline
* @param object $course
* @param object $user
* @param object $mod
* @param object $imscp
* @return object|null
*/
function imscp_user_outline($course, $user, $mod, $imscp) {
global $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'imscp',
'action'=>'view', 'info'=>$imscp->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$result = new stdClass();
$result->info = get_string('numviews', '', $numviews);
$result->time = $lastlog->time;
return $result;
}
return NULL;
}
/**
* Return use complete
* @param object $course
* @param object $user
* @param object $mod
* @param object $imscp
*/
function imscp_user_complete($course, $user, $mod, $imscp) {
global $CFG, $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'imscp',
'action'=>'view', 'info'=>$imscp->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$strmostrecently = get_string('mostrecently');
$strnumviews = get_string('numviews', '', $numviews);
echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
} else {
print_string('neverseen', 'imscp');
}
}
/**
* Lists all browsable file areas
*
......
......@@ -46,7 +46,6 @@ A page may be used
* To embed several videos or sound files together with some explanatory text';
$string['modulename_link'] = 'mod/page/view';
$string['modulenameplural'] = 'Pages';
$string['neverseen'] = 'Never seen';
$string['optionsheader'] = 'Display options';
$string['page-mod-page-x'] = 'Any page module page';
$string['page:addinstance'] = 'Add a new page resource';
......
......@@ -191,57 +191,6 @@ function page_delete_instance($id) {
return true;
}
/**
* Return use outline
* @param object $course
* @param object $user
* @param object $mod
* @param object $page
* @return object|null
*/
function page_user_outline($course, $user, $mod, $page) {
global $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'page',
'action'=>'view', 'info'=>$page->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$result = new stdClass();
$result->info = get_string('numviews', '', $numviews);
$result->time = $lastlog->time;
return $result;
}
return NULL;
}
/**
* Return use complete
* @param object $course
* @param object $user
* @param object $mod
* @param object $page
*/
function page_user_complete($course, $user, $mod, $page) {
global $CFG, $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'page',
'action'=>'view', 'info'=>$page->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$strmostrecently = get_string('mostrecently');
$strnumviews = get_string('numviews', '', $numviews);
echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
} else {
print_string('neverseen', 'page');
}
}
/**
* Given a course_module object, this function returns any
* "extra" information that may be needed when printing
......
......@@ -75,7 +75,6 @@ A file may be used
* To provide draft files of certain software programs (eg Photoshop .psd) so students can edit and submit them for assessment';
$string['modulename_link'] = 'mod/resource/view';
$string['modulenameplural'] = 'Files';
$string['neverseen'] = 'Never seen';
$string['notmigrated'] = 'This legacy resource type ({$a}) was not yet migrated, sorry.';
$string['optionsheader'] = 'Display options';
$string['page-mod-resource-x'] = 'Any file module page';
......
......@@ -177,57 +177,6 @@ function resource_delete_instance($id) {
return true;
}
/**
* Return use outline
* @param object $course
* @param object $user
* @param object $mod
* @param object $resource
* @return object|null
*/
function resource_user_outline($course, $user, $mod, $resource) {
global $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'resource',
'action'=>'view', 'info'=>$resource->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$result = new stdClass();
$result->info = get_string('numviews', '', $numviews);
$result->time = $lastlog->time;
return $result;
}
return NULL;
}
/**
* Return use complete
* @param object $course
* @param object $user
* @param object $mod
* @param object $resource
*/
function resource_user_complete($course, $user, $mod, $resource) {
global $CFG, $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'resource',
'action'=>'view', 'info'=>$resource->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$strmostrecently = get_string('mostrecently');
$strnumviews = get_string('numviews', '', $numviews);
echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
} else {
print_string('neverseen', 'resource');
}
}
/**
* Given a course_module object, this function returns any
* "extra" information that may be needed when printing
......
......@@ -8,6 +8,10 @@ information provided here is intended especially for developers.
$plugin instead. The support for the legacy notation will be dropped in Moodle 2.10.
* xxx_get_view_actions() and xxx_get_post_actions() will be ignored by new logging system for
participation report. view_action and post_action will be detected by event's crud and edulevel.
* The functions xxx_user_outline() and xxx_user_complete() have been removed from the majority of core modules (see MDL-41286),
except for those that require unique functionality. These functions are used by the outline report, but now if they no longer
exist, the default behaviour is chosen, which supports the legacy and standard log storages introduced in 2.7 (see MDL-41266).
It is highly recommended you remove these functions from your module if they are simply performing the default behaviour.
=== 2.6 ===
......
......@@ -54,7 +54,6 @@ There are a number of display options for the URL, such as embedded or opening i
Note that URLs can also be added to any other resource or activity type through the text editor.';
$string['modulename_link'] = 'mod/url/view';
$string['modulenameplural'] = 'URLs';
$string['neverseen'] = 'Never seen';
$string['page-mod-url-x'] = 'Any URL module page';
$string['parameterinfo'] = '&amp;parameter=variable';
$string['parametersheader'] = 'URL variables';
......
......@@ -193,57 +193,6 @@ function url_delete_instance($id) {
return true;
}
/**
* Return use outline
* @param object $course
* @param object $user
* @param object $mod
* @param object $url
* @return object|null
*/
function url_user_outline($course, $user, $mod, $url) {
global $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'url',
'action'=>'view', 'info'=>$url->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$result = new stdClass();
$result->info = get_string('numviews', '', $numviews);
$result->time = $lastlog->time;
return $result;
}
return NULL;
}
/**
* Return use complete
* @param object $course
* @param object $user
* @param object $mod
* @param object $url
*/
function url_user_complete($course, $user, $mod, $url) {
global $CFG, $DB;
if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'url',
'action'=>'view', 'info'=>$url->id), 'time ASC')) {
$numviews = count($logs);
$lastlog = array_pop($logs);
$strmostrecently = get_string('mostrecently');
$strnumviews = get_string('numviews', '', $numviews);
echo "$strnumviews - $strmostrecently ".userdate($lastlog->time);
} else {
print_string('neverseen', 'url');
}
}
/**
* Given a course_module object, this function returns any
* "extra" information that may be needed when printing
......
......@@ -194,32 +194,6 @@ function wiki_reset_course_form_definition(&$mform) {
$mform->addElement('advcheckbox', 'reset_wiki_comments', get_string('deleteallcomments'));
}
/**
* Return a small object with summary information about what a
* user has done with a given particular instance of this module
* Used for user activity reports.
* $return->time = the time they did it
* $return->info = a short text description
*
* @return null
* @todo Finish documenting this function
**/
function wiki_user_outline($course, $user, $mod, $wiki) {
$return = NULL;
return $return;
}
/**
* Print a detailed representation of what a user has done with
* a given particular instance of this module, for user activity reports.
*
* @return boolean
* @todo Finish documenting this function
**/
function wiki_user_complete($course, $user, $mod, $wiki) {
return true;
}
/**
* Indicates API features that the wiki supports.
*
......
......@@ -60,11 +60,32 @@ $PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($course->fullname));
if (!$logstart = $DB->get_field_sql("SELECT MIN(time) FROM {log}")) {
print_error('logfilenotavailable');
list($uselegacyreader, $useinternalreader, $minloginternalreader, $logtable) = report_outline_get_common_log_variables();
// If no legacy and no internal log then don't proceed.
if (!$uselegacyreader && !$useinternalreader) {
echo $OUTPUT->box_start('generalbox', 'notice');
echo $OUTPUT->notification(get_string('nologreaderenabled', 'report_outline'));
echo $OUTPUT->box_end();
echo $OUTPUT->footer();
die();
}
echo $OUTPUT->container(get_string('computedfromlogs', 'admin', userdate($logstart)), 'loginfo');
// We want to display the time we are beginning to get logs from in the heading.
// If we are using the legacy reader check the minimum time in that log table.
if ($uselegacyreader) {
$minlog = $DB->get_field_sql('SELECT min(time) FROM {log}');
}
// If we are using the internal reader check the minimum time in that table.
if ($useinternalreader) {
// If new log table has older data then don't use the minimum time obtained from the legacy table.
if (empty($minlog) || ($minloginternalreader <= $minlog)) {
$minlog = $minloginternalreader;
}
}
echo $OUTPUT->container(get_string('computedfromlogs', 'admin', userdate($minlog)), 'loginfo');
$outlinetable = new html_table();
$outlinetable->attributes['class'] = 'generaltable boxaligncenter';
......@@ -82,13 +103,65 @@ if ($showlastaccess) {
$modinfo = get_fast_modinfo($course);
$sql = "SELECT cm.id, COUNT('x') AS numviews, MAX(time) AS lasttime
// If using legacy log then get users from old table.
if ($uselegacyreader) {
// If we are going to use the internal (not legacy) log table, we should only get records
// from the legacy table that exist before we started adding logs to the new table.
$limittime = '';
if (!empty($minloginternalreader)) {
$limittime = ' AND time < :timeto ';
$params['timeto'] = $minloginternalreader;
}
// Check if we need to show the last access.
$sqllasttime = '';
if ($showlastaccess) {
$sqllasttime = ", MAX(time) AS lasttime";
}
$logactionlike = $DB->sql_like('l.action', ':action');
$sql = "SELECT cm.id, COUNT('x') AS numviews $sqllasttime
FROM {course_modules} cm
JOIN {modules} m ON m.id = cm.module
JOIN {log} l ON l.cmid = cm.id
WHERE cm.course = ? AND l.action LIKE 'view%' AND m.visible = 1
JOIN {modules} m
ON m.id = cm.module
JOIN {log} l
ON l.cmid = cm.id
WHERE cm.course = :courseid
AND $logactionlike
AND m.visible = :visible $limittime
GROUP BY cm.id";
$views = $DB->get_records_sql($sql, array($course->id));
$params = array('courseid' => $course->id, 'action' => 'view%', 'visible' => 1);
$views = $DB->get_records_sql($sql, $params);
}
// Get record from sql_internal_reader and merge with records obtained from legacy log (if needed).
if ($useinternalreader) {
// Check if we need to show the last access.
$sqllasttime = '';
if ($showlastaccess) {
$sqllasttime = ", MAX(timecreated) AS lasttime";
}
$sql = "SELECT contextinstanceid as cmid, COUNT('x') AS numviews $sqllasttime
FROM {" . $logtable . "} l
WHERE courseid = :courseid
AND anonymous = 0
AND crud = 'r'
AND contextlevel = :contextmodule
GROUP BY contextinstanceid";
$params = array('courseid' => $course->id, 'contextmodule' => CONTEXT_MODULE);
$v = $DB->get_records_sql($sql, $params);
if (empty($views)) {
$views = $v;
} else {
// Merge two view arrays.
foreach ($v as $key => $value) {
if (isset($views[$key]) && !empty($views[$key]->numviews)) {
$views[$key]->numviews += $value->numviews;
} else {
$views[$key] = $value;
}
}
}
}
$prevsecctionnum = 0;
foreach ($modinfo->sections as $sectionnum=>$section) {
......
......@@ -25,6 +25,8 @@
$string['eventactivityreportviewed'] = 'Activity report viewed';
$string['eventoutlinereportviewed'] = 'Outline report viewed';
$string['neverseen'] = 'Never seen';
$string['nologreaderenabled'] = 'No log reader enabled';
$string['outline:view'] = 'View activity report';
$string['page-report-outline-x'] = 'Any outline report';
$string['page-report-outline-index'] = 'Course outline report';
......
......@@ -53,3 +53,209 @@ function report_outline_print_row($mod, $instance, $result) {
}
echo "</tr>";
}
/**
* Returns an array of the commonly used log variables by the outline report.
*
* @return array the array of variables used
*/
function report_outline_get_common_log_variables() {
global $DB;
static $uselegacyreader;
static $useinternalreader;
static $minloginternalreader;
static $logtable = null;
if (isset($uselegacyreader) && isset($useinternalreader) && isset($minloginternalreader)) {
return array($uselegacyreader, $useinternalreader, $minloginternalreader, $logtable);
}
$uselegacyreader = false; // Flag to determine if we should use the legacy reader.
$useinternalreader = false; // Flag to determine if we should use the internal reader.
$minloginternalreader = 0; // Set this to 0 for now.
// Get list of readers.
$logmanager = get_log_manager();
$readers = $logmanager->get_readers();
// Get preferred reader.
if (!empty($readers)) {
foreach ($readers as $readerpluginname => $reader) {
// If legacy reader is preferred reader.
if ($readerpluginname == 'logstore_legacy') {
$uselegacyreader = true;
break;
}
// If sql_internal_reader is preferred reader.