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 "

$image $mod->modfullname: ". - "wwwroot/mod/$mod->modname/view.php?id=$mod->id\">". - format_string($instance->name,true)."

"; - - ob_start(); - - 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 "

$image $mod->modfullname: ". + "wwwroot/mod/$mod->modname/view.php?id=$mod->id\">". + format_string($instance->name,true)."

"; + + 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;