diff --git a/course/user.php b/course/user.php
index 1face9aef98..2a47814b9f8 100644
--- a/course/user.php
+++ b/course/user.php
@@ -49,6 +49,11 @@ if (! $user = $DB->get_record("user", array("id"=>$user))) {
print_error('invaliduserid', 'error');
}
+if ($mode === 'outline' or $mode === 'complete') {
+ $url = new moodle_url('/report/outline/user.php', array('id'=>$user->id, 'course'=>$course->id, 'mode'=>$mode));
+ redirect($url);
+}
+
require_login();
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
$personalcontext = get_context_instance(CONTEXT_USER, $user->id);
@@ -77,14 +82,6 @@ $anyreport = has_capability('moodle/user:viewuseractivitiesreport', $personalco
$modes = array();
-if ($myreports or $anyreport or has_capability('report/outline:view', $coursecontext)) {
- $modes[] = 'outline';
-}
-
-if ($myreports or $anyreport or has_capability('report/outline:view', $coursecontext)) {
- $modes[] = 'complete';
-}
-
if ($myreports or $anyreport or has_capability('report/log:viewtoday', $coursecontext)) {
$modes[] = 'todaylogs';
}
@@ -140,7 +137,6 @@ add_to_log($course->id, "course", "user report", "user.php?id=$course->id&us
$stractivityreport = get_string("activityreport");
$strparticipants = get_string("participants");
-$stroutline = get_string("outline");
$strcomplete = get_string("complete");
$stralllogs = get_string("alllogs");
$strtodaylogs = get_string("todaylogs");
@@ -267,101 +263,6 @@ switch ($mode) {
echo html_writer::table($table);
break;
- case "outline" :
- case "complete" :
- get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
- $sections = get_all_sections($course->id);
- $itemsprinted = false;
-
- for ($i=0; $i<=$course->numsections; $i++) {
-
- if (isset($sections[$i])) { // should always be true
-
- $section = $sections[$i];
- $showsection = (has_capability('moodle/course:viewhiddensections', $coursecontext) or $section->visible or !$course->hiddensections);
-
- if ($showsection) { // prevent hidden sections in user activity. Thanks to Geoff Wilbert!
- // Check the section has a sequence. This is the sequence of modules/resources.
- // If there is no sequence there is nothing to display.
- if ($section->sequence) {
- $itemsprinted = true;
- echo '
';
- echo '
';
- echo get_section_name($course, $section);
- echo "
";
-
- echo '
';
-
- if ($mode == "outline") {
- echo "
";
- }
-
- $sectionmods = explode(",", $section->sequence);
- foreach ($sectionmods as $sectionmod) {
- if (empty($mods[$sectionmod])) {
- continue;
- }
- $mod = $mods[$sectionmod];
-
- if (empty($mod->visible)) {
- continue;
- }
-
- $instance = $DB->get_record("$mod->modname", array("id"=>$mod->instance));
- $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
-
- if (file_exists($libfile)) {
- require_once($libfile);
-
- switch ($mode) {
- case "outline":
- $user_outline = $mod->modname."_user_outline";
- if (function_exists($user_outline)) {
- $output = $user_outline($course, $user, $mod, $instance);
- print_outline_row($mod, $instance, $output);
- }
- break;
- case "complete":
- $user_complete = $mod->modname."_user_complete";
- if (function_exists($user_complete)) {
- $image = $OUTPUT->pix_icon('icon', $mod->modfullname, 'mod_'.$mod->modname, array('class'=>'icon'));
- echo "";
-
- ob_start();
-
- echo "";
- $user_complete($course, $user, $mod, $instance);
- echo "
";
-
- $output = ob_get_contents();
- ob_end_clean();
-
- if (str_replace(' ', '', $output) != '') {
- echo $output;
- }
- }
- break;
- }
- }
- }
-
- if ($mode == "outline") {
- echo "
";
- }
- echo '
'; // content
- echo '
'; // section
- }
- }
- }
- }
-
- if (!$itemsprinted) {
- echo $OUTPUT->notification(get_string('nothingtodisplay'));
- }
-
- break;
case "coursecompletion":
case "coursecompletions":
@@ -608,31 +509,3 @@ switch ($mode) {
echo $OUTPUT->footer();
-
-
-function print_outline_row($mod, $instance, $result) {
- global $OUTPUT;
-
- $image = "
pix_url('icon', $mod->modname) . "\" class=\"icon\" alt=\"$mod->modfullname\" />";
-
- echo "";
- echo "| $image | ";
- echo "";
- echo " modfullname\"";
- echo " href=\"../mod/$mod->modname/view.php?id=$mod->id\">".format_string($instance->name,true)." | ";
- echo " | ";
- echo "";
- if (isset($result->info)) {
- echo "$result->info";
- } else {
- echo " - ";
- }
- echo " | ";
- echo " | ";
- if (!empty($result->time)) {
- $timeago = format_time(time() - $result->time);
- echo "".userdate($result->time)." ($timeago) | ";
- }
- echo "
";
-}
-
diff --git a/lib/navigationlib.php b/lib/navigationlib.php
index 74d57b9f51c..7d9a0ae4cf3 100644
--- a/lib/navigationlib.php
+++ b/lib/navigationlib.php
@@ -1831,11 +1831,12 @@ class global_navigation extends navigation_node {
return false;
}
/**
- * Loads user specific information into the navigation in the appopriate place.
+ * Loads user specific information into the navigation in the appropriate place.
*
* If no user is provided the current user is assumed.
*
* @param stdClass $user
+ * @param bool $forceforcontext probably force something to be loaded somewhere (ask SamH if not sure what this means)
* @return bool
*/
protected function load_for_user($user=null, $forceforcontext=false) {
@@ -1972,31 +1973,32 @@ class global_navigation extends navigation_node {
$usernode->add(get_string('notes', 'notes'), $url);
}
- //TODO: all this is a hack - we can not link to plugins like this - all this must be abstracted to plugin callbacks!
+ $reporttab = $usernode->add(get_string('activityreports'));
+
+ $reports = get_plugin_list_with_function('report', 'extend_navigation_user', 'lib.php');
+ foreach ($reports as $reportfunction) {
+ $reportfunction($reporttab, $user, $course);
+ }
+
+ //TODO: hack area alert - all this must be abstracted to plugin callbacks above
// Add a reports tab and then add reports the the user has permission to see.
$anyreport = has_capability('moodle/user:viewuseractivitiesreport', $usercontext);
- $outlinetreport = ($anyreport || has_capability('report/outline:view', $coursecontext));
$logtodayreport = ($anyreport || has_capability('report/log:viewtoday', $coursecontext));
$logreport = ($anyreport || has_capability('report/log:view', $coursecontext));
$statsreport = ($anyreport || has_capability('report/stats:view', $coursecontext));
- $somereport = $outlinetreport || $logtodayreport || $logreport || $statsreport;
+ $somereport = $logtodayreport || $logreport || $statsreport;
$viewreports = ($anyreport || $somereport || ($course->showreports && $iscurrentuser && $forceforcontext));
if ($viewreports) {
- $reporttab = $usernode->add(get_string('activityreports'));
$reportargs = array('user'=>$user->id);
if (!empty($course->id)) {
$reportargs['id'] = $course->id;
} else {
$reportargs['id'] = SITEID;
}
- if ($viewreports || $outlinetreport) {
- $reporttab->add(get_string('outlinereport'), new moodle_url('/course/user.php', array_merge($reportargs, array('mode'=>'outline'))));
- $reporttab->add(get_string('completereport'), new moodle_url('/course/user.php', array_merge($reportargs, array('mode'=>'complete'))));
- }
if ($viewreports || $logtodayreport) {
$reporttab->add(get_string('todaylogs'), new moodle_url('/course/user.php', array_merge($reportargs, array('mode'=>'todaylogs'))));
@@ -2037,6 +2039,12 @@ class global_navigation extends navigation_node {
$reporttab->trim_if_empty();
}
+ //TODO: end of hacky area
+
+ // Check the number of nodes in the report node... if there are none remove
+ // the node
+ $reporttab->trim_if_empty();
+
// If the user is the current user add the repositories for the current user
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
if ($iscurrentuser) {
@@ -2092,17 +2100,20 @@ class global_navigation extends navigation_node {
$usercoursenode->add(get_string('entercourse'), new moodle_url('/course/view.php', array('id'=>$usercourse->id)), self::TYPE_SETTING, null, null, new pix_icon('i/course', ''));
}
- $outlinetreport = ($anyreport || has_capability('report/outline:view', $usercoursecontext));
+ $reporttab = $usercoursenode->add(get_string('activityreports'));
+
+ $reports = get_plugin_list_with_function('report', 'extend_navigation_user', 'lib.php');
+ foreach ($reports as $reportfunction) {
+ $reportfunction($reporttab, $user, $usercourse);
+ }
+
+ //TODO: hacky area - migrate to plugin callbacks above
+
$logtodayreport = ($anyreport || has_capability('report/log:viewtoday', $usercoursecontext));
$logreport = ($anyreport || has_capability('report/log:view', $usercoursecontext));
$statsreport = ($anyreport || has_capability('report/stats:view', $usercoursecontext));
- if ($outlinetreport || $logtodayreport || $logreport || $statsreport) {
- $reporttab = $usercoursenode->add(get_string('activityreports'));
+ if ($logtodayreport || $logreport || $statsreport) {
$reportargs = array('user'=>$user->id, 'id'=>$usercourse->id);
- if ($outlinetreport) {
- $reporttab->add(get_string('outlinereport'), new moodle_url('/course/user.php', array_merge($reportargs, array('mode'=>'outline'))));
- $reporttab->add(get_string('completereport'), new moodle_url('/course/user.php', array_merge($reportargs, array('mode'=>'complete'))));
- }
if ($logtodayreport) {
$reporttab->add(get_string('todaylogs'), new moodle_url('/course/user.php', array_merge($reportargs, array('mode'=>'todaylogs'))));
@@ -2116,6 +2127,10 @@ class global_navigation extends navigation_node {
$reporttab->add(get_string('stats'), new moodle_url('/course/user.php', array_merge($reportargs, array('mode'=>'stats'))));
}
}
+
+ //TODO: end of hacky area
+
+ $reporttab->trim_if_empty();
}
}
return true;
diff --git a/report/outline/index.php b/report/outline/index.php
index 11fc36407e5..b41a0da368e 100644
--- a/report/outline/index.php
+++ b/report/outline/index.php
@@ -24,7 +24,7 @@
*/
require('../../config.php');
-require_once($CFG->dirroot.'/course/lib.php');
+require_once($CFG->dirroot.'/report/outline/locallib.php');
$id = required_param('id',PARAM_INT); // course id
diff --git a/report/outline/lib.php b/report/outline/lib.php
index 0d0e422f1a1..df7dfa85fbc 100644
--- a/report/outline/lib.php
+++ b/report/outline/lib.php
@@ -15,7 +15,7 @@
// along with Moodle. If not, see .
/**
- * This file contains functions used by the outline report
+ * This file contains public API of outline report
*
* @package report
* @subpackage outline
@@ -33,13 +33,61 @@ defined('MOODLE_INTERNAL') || die;
* @param stdClass $context The context of the course
*/
function report_outline_extend_navigation_course($navigation, $course, $context) {
- global $CFG, $OUTPUT;
if (has_capability('report/outline:view', $context)) {
$url = new moodle_url('/report/outline/index.php', array('id'=>$course->id));
$navigation->add(get_string('pluginname', 'report_outline'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', ''));
}
}
+/**
+ * This function extends the course navigation with the report items
+ *
+ * @param navigation_node $navigation The navigation node to extend
+ * @param stdClass $user
+ * @param stdClass $course The course to object for the report
+ */
+function report_outline_extend_navigation_user($navigation, $user, $course) {
+ if (report_outline_can_access_user_report($user, $course)) {
+ $url = new moodle_url('/report/outline/user.php', array('id'=>$user->id, 'course'=>$course->id, 'mode'=>'outline'));
+ $navigation->add(get_string('outlinereport'), $url);
+ $url = new moodle_url('/report/outline/user.php', array('id'=>$user->id, 'course'=>$course->id, 'mode'=>'complete'));
+ $navigation->add(get_string('completereport'), $url);
+ }
+}
+
+/**
+ * Is current user allowed to access this report
+ *
+ * @private defined in lib.php for performance reasons
+ *
+ * @param stdClass $user
+ * @param stdClass $course
+ * @return bool
+ */
+function report_outline_can_access_user_report($user, $course) {
+ global $USER;
+
+ $coursecontext = context_course::instance($course->id);
+ $personalcontext = context_user::instance($user->id);
+
+ if (has_capability('report/outline:view', $coursecontext)) {
+ return true;
+ }
+
+ if (has_capability('moodle/user:viewuseractivitiesreport', $personalcontext)) {
+ if ($course->showreports and (is_viewing($coursecontext, $user) or is_enrolled($coursecontext, $user))) {
+ return true;
+ }
+
+ } else if ($user->id == $USER->id) {
+ if ($course->showreports and (is_viewing($coursecontext, $USER) or is_enrolled($coursecontext, $USER))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* Return a list of page types
* @param string $pagetype current page type
@@ -54,4 +102,4 @@ function report_outline_page_type_list($pagetype, $parentcontext, $currentcontex
'course-report-outline-index' => get_string('pluginpagetype', 'report_outline')
);
return $array;
-}
\ No newline at end of file
+}
diff --git a/report/outline/locallib.php b/report/outline/locallib.php
new file mode 100644
index 00000000000..ba4761cc558
--- /dev/null
+++ b/report/outline/locallib.php
@@ -0,0 +1,55 @@
+.
+
+/**
+ * This file contains functions used by the outline reports
+ *
+ * @package report
+ * @subpackage outline
+ * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+require_once(dirname(__FILE__).'/lib.php');
+require_once($CFG->dirroot.'/course/lib.php');
+
+function report_outline_print_row($mod, $instance, $result) {
+ global $OUTPUT, $CFG;
+
+ $image = "
pix_url('icon', $mod->modname) . "\" class=\"icon\" alt=\"$mod->modfullname\" />";
+
+ echo "";
+ echo "| $image | ";
+ echo "";
+ echo " modfullname\"";
+ echo " href=\"$CFG->wwwroot/mod/$mod->modname/view.php?id=$mod->id\">".format_string($instance->name,true)." | ";
+ echo " | ";
+ echo "";
+ if (isset($result->info)) {
+ echo "$result->info";
+ } else {
+ echo " - ";
+ }
+ echo " | ";
+ echo " | ";
+ if (!empty($result->time)) {
+ $timeago = format_time(time() - $result->time);
+ echo "".userdate($result->time)." ($timeago) | ";
+ }
+ echo "
";
+}
diff --git a/report/outline/styles.css b/report/outline/styles.css
index 528d22c4ac9..aff09a74a30 100644
--- a/report/outline/styles.css
+++ b/report/outline/styles.css
@@ -1,3 +1,8 @@
#page-report-outline-index td.numviews {text-align:right;}
#page-report-outline-index tr.section {text-align: center;}
#page-report-outline-index td.lastaccess {font-size: 0.8em;}
+
+#page-report-outline-user .section .content {margin-left: 30px;margin-right: 30px;}
+#page-report-outline-user .section h2 {margin-top: 0;}
+#page-report-outline-user .section {margin-left: 30px;margin-right: 30px;margin-bottom: 20px;}
+#page-report-outline-user .section {border-width:1px;border-style:solid;padding:10px;}
diff --git a/report/outline/user.php b/report/outline/user.php
new file mode 100644
index 00000000000..2921c0cd774
--- /dev/null
+++ b/report/outline/user.php
@@ -0,0 +1,161 @@
+.
+
+/**
+ * Display user activity reports for a course (totals)
+ *
+ * @package report
+ * @subpackage outline
+ * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require('../../config.php');
+require_once($CFG->dirroot.'/report/outline/locallib.php');
+
+$userid = required_param('id', PARAM_INT);
+$courseid = required_param('course', PARAM_INT);
+$mode = optional_param('mode', 'outline', PARAM_ALPHA);
+
+if ($mode !== 'complete' and $mode !== 'outline') {
+ $mode = 'outline';
+}
+
+$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);
+
+if ($USER->id != $user->id and has_capability('moodle/user:viewuseractivitiesreport', $personalcontext)
+ and !is_enrolled($coursecontext, $USER) and is_enrolled($coursecontext, $user)) {
+ //TODO: do not require parents to be enrolled in courses - this is a hack!
+ require_login();
+ $PAGE->set_course($course);
+} else {
+ require_login($course);
+}
+
+if (!report_outline_can_access_user_report($user, $course, true)) {
+ require_capability('report/outline:view', $coursecontext);
+}
+
+add_to_log($course->id, 'course', 'report outline', "report/outline/user.php?id=$user->id&course=$course->id&mode=$mode", $course->id);
+
+$stractivityreport = get_string('activityreport');
+
+$PAGE->set_pagelayout('admin');
+$PAGE->set_url('/report/outline/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");
+$PAGE->set_heading($course->fullname);
+echo $OUTPUT->header();
+
+
+get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
+$sections = get_all_sections($course->id);
+$itemsprinted = false;
+
+for ($i=0; $i<=$course->numsections; $i++) {
+
+ if (isset($sections[$i])) { // should always be true
+
+ $section = $sections[$i];
+ $showsection = (has_capability('moodle/course:viewhiddensections', $coursecontext) or $section->visible or !$course->hiddensections);
+
+ if ($showsection) { // prevent hidden sections in user activity. Thanks to Geoff Wilbert!
+ // Check the section has a sequence. This is the sequence of modules/resources.
+ // If there is no sequence there is nothing to display.
+ if ($section->sequence) {
+ $itemsprinted = true;
+ echo '';
+ echo '
';
+ echo get_section_name($course, $section);
+ echo "
";
+
+ echo '
';
+
+ if ($mode == "outline") {
+ echo "
";
+ }
+
+ $sectionmods = explode(",", $section->sequence);
+ foreach ($sectionmods as $sectionmod) {
+ if (empty($mods[$sectionmod])) {
+ continue;
+ }
+ $mod = $mods[$sectionmod];
+
+ if (empty($mod->visible)) {
+ continue;
+ }
+
+ $instance = $DB->get_record("$mod->modname", array("id"=>$mod->instance));
+ $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
+
+ if (file_exists($libfile)) {
+ require_once($libfile);
+
+ switch ($mode) {
+ case "outline":
+ $user_outline = $mod->modname."_user_outline";
+ if (function_exists($user_outline)) {
+ $output = $user_outline($course, $user, $mod, $instance);
+ report_outline_print_row($mod, $instance, $output);
+ }
+ break;
+ case "complete":
+ $user_complete = $mod->modname."_user_complete";
+ if (function_exists($user_complete)) {
+ $image = $OUTPUT->pix_icon('icon', $mod->modfullname, 'mod_'.$mod->modname, array('class'=>'icon'));
+ echo "";
+
+ ob_start();
+
+ echo "";
+ $user_complete($course, $user, $mod, $instance);
+ echo "
";
+
+ $output = ob_get_contents();
+ ob_end_clean();
+
+ if (str_replace(' ', '', $output) != '') {
+ echo $output;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if ($mode == "outline") {
+ echo "
";
+ }
+ echo '
'; // content
+ echo '
'; // section
+ }
+ }
+ }
+}
+
+if (!$itemsprinted) {
+ echo $OUTPUT->notification(get_string('nothingtodisplay'));
+}
+
+echo $OUTPUT->footer();
diff --git a/theme/anomaly/style/general.css b/theme/anomaly/style/general.css
index 671d2ee8415..22e3cd211de 100644
--- a/theme/anomaly/style/general.css
+++ b/theme/anomaly/style/general.css
@@ -37,11 +37,11 @@ html, body {background-color:#C8C9C7;}
.course-content .section.main .content {margin:0 30px 10px 30px;background-color:#FFF;}
.course-content .section.main .content .section_add_menus {text-align:right;}
-#course-user .section {border:1px solid #DDD;margin:0 5% 1.5em 5%;}
+#page-report-outline-user .section {border:1px solid #DDD;margin:0 5% 1.5em 5%;}
-#course-user .section h2,
-#course-user .section .content {margin:5px 1em;}
-#course-user .section table td {border:0;}
+#page-report-outline-user .section h2,
+#page-report-outline-user .section .content {margin:5px 1em;}
+#page-report-outline-user .section table td {border:0;}
.generaltable {border:1px solid #DDD;}
.generaltable .cell {background-color:#FFF;border:1px solid #EEE;border-collapse: collapse;}
diff --git a/theme/base/style/course.css b/theme/base/style/course.css
index 80b1fa00978..0e4f3f9ca0a 100644
--- a/theme/base/style/course.css
+++ b/theme/base/style/course.css
@@ -34,9 +34,6 @@
#page-course-enrol .generalbox,
#page-course-enrol .coursebox {margin-top: 20px;}
-#page-course-user .section {margin-left: 30px;margin-right: 30px;margin-bottom: 20px;}
-#page-course-user .section .content {margin-left: 30px;margin-right: 30px;}
-#page-course-user .section h2 {margin-top: 0;}
#page-course-user .info {margin:10px;}
#page-course-pending .singlebutton,
@@ -82,7 +79,6 @@
.weeks-format, /* Window-width: 800 pixels.IE doesn't support, see inline IE conditional comment. */
.topics-format {margin-top: 8px;min-width: 763px;}
-#page-course-user .section {border-width:1px;border-style:solid;padding:10px;}
.categoryboxcontent {border-width:1px;border-style:solid;}
/* Course and category combo list on front page */
diff --git a/theme/formal_white/style/course.css b/theme/formal_white/style/course.css
index d31d5e1ffda..b7e7e24d843 100644
--- a/theme/formal_white/style/course.css
+++ b/theme/formal_white/style/course.css
@@ -59,7 +59,7 @@
.categoryboxcontent {border-color:#DDDDDD;}
#page-course-user .graph {text-align:center;}
-#page-course-user .section {border-color:#AAAAAA;}
+#page-report-outline-user .section {border-color:#AAAAAA;}
#page-course-user .info {text-align:center;}
#page-admin-report .plugin,
diff --git a/theme/standard/style/course.css b/theme/standard/style/course.css
index 8aeb11d5c86..f87d2b8ac62 100644
--- a/theme/standard/style/course.css
+++ b/theme/standard/style/course.css
@@ -56,7 +56,7 @@
.categoryboxcontent {border-color:#DDDDDD;}
#page-course-user .graph {text-align: center;}
-#page-course-user .section {border-color:#AAAAAA;}
+#page-report-outline-user .section {border-color:#AAAAAA;}
#page-course-user .info {text-align:center;}
#page-admin-report .plugin,
diff --git a/theme/standard/style/css3.css b/theme/standard/style/css3.css
index cf17e84aca5..32677ad27d2 100644
--- a/theme/standard/style/css3.css
+++ b/theme/standard/style/css3.css
@@ -76,7 +76,7 @@ table.minicalendar {
.block_course_summary,
.block_course_summary .content,
-#page-course-user .section {
+#page-report-outline-user .section {
-moz-border-radius:10px;
-webkit-border-radius: 10px;
border-radius: 10px;