diff --git a/admin/settings/appearance.php b/admin/settings/appearance.php index 70c564f4057..d6eb80fdd34 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -27,7 +27,8 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp 'customusermenuitems', new lang_string('customusermenuitems', 'admin'), new lang_string('configcustomusermenuitems', 'admin'), - 'messages,message|/message/index.php|message + 'mygrades,grades|/grade/report/mygrades.php|grades +messages,message|/message/index.php|message myfiles,moodle|/user/files.php|download mybadges,badges|/badges/mybadges.php|award', PARAM_TEXT, diff --git a/admin/settings/grades.php b/admin/settings/grades.php index 15a429e8f28..2d9ed385e4d 100644 --- a/admin/settings/grades.php +++ b/admin/settings/grades.php @@ -75,6 +75,11 @@ if (has_capability('moodle/grade:manage', $systemcontext) $temp->add(new admin_setting_special_gradepointmax()); $temp->add(new admin_setting_special_gradepointdefault()); + + $temp->add(new admin_setting_my_grades_report()); + + $temp->add(new admin_setting_configtext('gradereport_mygradeurl', new lang_string('externalurl', 'grades'), + new lang_string('externalurl_desc', 'grades'), null)); } $ADMIN->add('grades', $temp); diff --git a/course/user.php b/course/user.php index 8b68c776432..3320c3e360d 100644 --- a/course/user.php +++ b/course/user.php @@ -124,10 +124,24 @@ $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 ($mode)"); $PAGE->set_heading($course->fullname); -echo $OUTPUT->header(); switch ($mode) { case "grade": + // Change the navigation to point to the my grade node (If we are a student). + if ($USER->id == $user->id) { + require_once($CFG->dirroot . '/user/lib.php'); + // Get the correct 'My grades' url to point to. + $activeurl = user_mygrades_url(); + $PAGE->navigation->override_active_url($activeurl); + $activenode = $PAGE->navbar->add($course->shortname); + $activenode->make_active(); + // Find the course node and collapse it. + $coursenode = $PAGE->navigation->find($course->id, navigation_node::TYPE_COURSE); + $coursenode->collapse = true; + $coursenode->make_inactive(); + } + echo $OUTPUT->header(); + if (empty($CFG->grade_profilereport) or !file_exists($CFG->dirroot.'/grade/report/'.$CFG->grade_profilereport.'/lib.php')) { $CFG->grade_profilereport = 'user'; } @@ -144,6 +158,8 @@ switch ($mode) { break; default: // can not be reached ;-) + // But just incase let's not break the navigation. + echo $OUTPUT->header(); } diff --git a/grade/report/lib.php b/grade/report/lib.php index b0aa35b76ae..bd30489cd53 100644 --- a/grade/report/lib.php +++ b/grade/report/lib.php @@ -353,6 +353,13 @@ abstract class grade_report { return $count; } + /** + * Shows support for being used as a 'My grades' report. + */ + public static function supports_mygrades() { + return false; + } + /** * Sets up this object's group variables, mainly to restrict the selection of users to display. */ diff --git a/grade/report/mygrades.php b/grade/report/mygrades.php new file mode 100644 index 00000000000..876e34b91f6 --- /dev/null +++ b/grade/report/mygrades.php @@ -0,0 +1,33 @@ +. + +/** + * Redirects the user to the default grade report. + * + * @package core_grades + * @copyright 2015 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../../config.php'); +require_once($CFG->dirroot . '/user/lib.php'); + +defined('MOODLE_INTERNAL') || die(); + +// Get the url to redirect to. +$url = user_mygrades_url(); +// Redirect to that page. +redirect($url); diff --git a/grade/report/overview/index.php b/grade/report/overview/index.php index 3723f24e21a..c8c11ed2857 100644 --- a/grade/report/overview/index.php +++ b/grade/report/overview/index.php @@ -27,20 +27,25 @@ require_once $CFG->libdir.'/gradelib.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/overview/lib.php'; -$courseid = required_param('id', PARAM_INT); +$courseid = optional_param('id', SITEID, PARAM_INT); $userid = optional_param('userid', $USER->id, PARAM_INT); -$PAGE->set_url(new moodle_url('/grade/report/overview/index.php', array('id'=>$courseid))); +$PAGE->set_url(new moodle_url('/grade/report/overview/index.php', array('id' => $courseid, 'userid' => $userid))); -/// basic access checks if (!$course = $DB->get_record('course', array('id' => $courseid))) { print_error('nocourseid'); } -require_login($course); +require_login(null, false); $context = context_course::instance($course->id); $systemcontext = context_system::instance(); -require_capability('gradereport/overview:view', $context); +$personalcontext = null; +$PAGE->set_context($context); + +// If we are accessing the page from a site context then ignore this check. +if ($courseid != SITEID) { + require_capability('gradereport/overview:view', $context); +} if (empty($userid)) { require_capability('moodle/grade:viewall', $context); @@ -49,6 +54,7 @@ if (empty($userid)) { if (!$DB->get_record('user', array('id'=>$userid, 'deleted'=>0)) or isguestuser($userid)) { print_error('invaliduserid'); } + $personalcontext = context_user::instance($userid); } $access = false; @@ -60,12 +66,16 @@ if (has_capability('moodle/grade:viewall', $systemcontext)) { // Ok - can view any grades in context. $access = true; -} else if ($userid == $USER->id and has_capability('moodle/grade:view', $context) and $course->showgrades) { +} else if ($userid == $USER->id and ((has_capability('moodle/grade:view', $context) and $course->showgrades) + || $courseid == SITEID)) { // Ok - can view own course grades. $access = true; -} else if (has_capability('moodle/grade:viewall', context_user::instance($userid)) and $course->showgrades) { - // Ok - can view grades of this user- parent most probably. +} else if (has_capability('moodle/grade:viewall', $personalcontext) and $course->showgrades) { + // Ok - can view grades of this user - parent most probably. + $access = true; +} else if (has_capability('moodle/user:viewuseractivitiesreport', $personalcontext) and $course->showgrades) { + // Ok - can view grades of this user - parent most probably. $access = true; } @@ -86,7 +96,7 @@ $USER->grade_last_report[$course->id] = 'overview'; //first make sure we have proper final grades - this must be done before constructing of the grade tree grade_regrade_final_grades($courseid); -if (has_capability('moodle/grade:viewall', $context)) { +if (has_capability('moodle/grade:viewall', $context) && $courseid != SITEID) { // Please note this would be extremely slow if we wanted to implement this properly for all teachers. $groupmode = groups_get_course_groupmode($course); // Groups are being used $currentgroup = groups_get_course_group($course, true); @@ -135,16 +145,38 @@ if (has_capability('moodle/grade:viewall', $context)) { } } } -} else { //Non-admins will see just their own report +} else { // Non-admins and users viewing from the site context can just see their own report. // Create a report instance $report = new grade_report_overview($userid, $gpr, $context); - // print the page - print_grade_page_head($courseid, 'report', 'overview', get_string('pluginname', 'gradereport_overview'). ' - '.fullname($report->user)); + // If the course id matches the site id then we don't have a course context to work with. + // Display a standard page. + if ($courseid == SITEID) { + $PAGE->set_pagelayout('standard'); + $header = get_string('mygrades', 'grades'). ' - '.fullname($report->user); + $PAGE->set_title($header); + $PAGE->set_heading($header); - if ($report->fill_table()) { - echo '
'.$report->print_table(true); + if ($USER->id != $report->user->id) { + $PAGE->navigation->extend_for_user($report->user); + if ($node = $PAGE->settingsnav->get('userviewingsettings'.$report->user->id)) { + $node->forceopen = true; + } + } else if ($node = $PAGE->settingsnav->get('usercurrentsettings', navigation_node::TYPE_CONTAINER)) { + $node->forceopen = true; + } + + echo $OUTPUT->header(); + if ($report->fill_table(true)) { + echo '
'.$report->print_table(true); + } + } else { // We have a course context. We must be navigating from the gradebook. + print_grade_page_head($courseid, 'report', 'overview', get_string('pluginname', 'gradereport_overview') + . ' - ' . fullname($report->user)); + if ($report->fill_table()) { + echo '
'.$report->print_table(true); + } } } diff --git a/grade/report/overview/lib.php b/grade/report/overview/lib.php index a68b6e9a1e2..8d039104109 100644 --- a/grade/report/overview/lib.php +++ b/grade/report/overview/lib.php @@ -134,7 +134,12 @@ class grade_report_overview extends grade_report { $this->table->setup(); } - public function fill_table() { + /** + * Fill the table for displaying. + * + * @param bool $activitylink If this report link to the activity report or the user report. + */ + public function fill_table($activitylink = false) { global $CFG, $DB, $OUTPUT, $USER; // Only show user's courses instead of all courses. @@ -153,13 +158,21 @@ class grade_report_overview extends grade_report { continue; } - if ((!has_capability('moodle/grade:view', $coursecontext) || $this->user->id != $USER->id) && - !has_capability('moodle/grade:viewall', $coursecontext)) { + if (!has_capability('moodle/user:viewuseractivitiesreport', context_user::instance($this->user->id)) && + ((!has_capability('moodle/grade:view', $coursecontext) || $this->user->id != $USER->id) && + !has_capability('moodle/grade:viewall', $coursecontext))) { continue; } - $courseshortname = format_string(get_course_display_name_for_list($course), true, array('context' => $coursecontext)); - $courselink = html_writer::link(new moodle_url('/grade/report/user/index.php', array('id' => $course->id, 'userid' => $this->user->id)), $courseshortname); + $coursename = format_string(get_course_display_name_for_list($course), true, array('context' => $coursecontext)); + // Link to the activity report version of the user grade report. + if ($activitylink) { + $courselink = html_writer::link(new moodle_url('/course/user.php', array('mode' => 'grade', 'id' => $course->id, + 'user' => $this->user->id)), $coursename); + } else { + $courselink = html_writer::link(new moodle_url('/grade/report/user/index.php', array('id' => $course->id, + 'userid' => $this->user->id)), $coursename); + } $canviewhidden = has_capability('moodle/grade:viewhidden', $coursecontext); // Get course grade_item @@ -221,7 +234,7 @@ class grade_report_overview extends grade_report { return true; } else { - echo $OUTPUT->notification(get_string('nocourses', 'grades')); + echo $OUTPUT->notification(get_string('notenrolled', 'grades'), 'notifymessage'); return false; } } @@ -251,6 +264,13 @@ class grade_report_overview extends grade_report { } function process_action($target, $action) { } + + /** + * This report supports being set as the 'my grades' report. + */ + public static function supports_mygrades() { + return true; + } } function grade_report_overview_settings_definition(&$mform) { diff --git a/lang/en/grades.php b/lang/en/grades.php index a15d5228f7a..0c086c23dd7 100644 --- a/lang/en/grades.php +++ b/lang/en/grades.php @@ -206,6 +206,8 @@ $string['exportsettings'] = 'Export settings'; $string['exportonlyactive'] = 'Exclude suspended users'; $string['exportonlyactive_help'] = 'Only include students in the export whose enrolment is active and has not been suspended'; $string['exportto'] = 'Export to'; +$string['externalurl'] = 'External URL'; +$string['externalurl_desc'] = 'Specify an external url to use for the my grade page. My grades must be set to External URL.'; $string['extracreditvalue'] = 'Extra credit value for {$a}'; $string['extracreditwarning'] = 'Note: Setting all items for a category to extra credit will effectively remove them from the grade calculation. Since there will be no point total'; $string['feedback'] = 'Feedback'; @@ -455,6 +457,8 @@ $string['movingelement'] = 'Moving {$a}'; $string['multfactor'] = 'Multiplicator'; $string['multfactorvalue'] = 'Multiplicator value for {$a}'; $string['multfactor_help'] = 'The multiplicator is the factor by which all grades for this grade item will be multiplied, with a maximum value of the maximum grade. For example, if the multiplicator is 2 and the maximum grade is 100, then all grades less than 50 are multiplied by 2, and all grades 50 and above are changed to 100.'; +$string['mygrades'] = 'My grades'; +$string['mygrades_desc'] = 'This sets the "My grades" page in the user menu.'; $string['mypreferences'] = 'My preferences'; $string['myreportpreferences'] = 'My report preferences'; $string['navmethod'] = 'Navigation method'; @@ -485,6 +489,7 @@ $string['noscales'] = 'Outcomes must be linked to a course scale or global scale $string['noselectedcategories'] = 'no categories were selected.'; $string['noselecteditems'] = 'no items were selected.'; $string['notteachererror'] = 'You must be a teacher to use this feature.'; +$string['notenrolled'] = 'You are currently not enrolled in any courses.'; $string['nousersloaded'] = 'No users loaded'; $string['numberofgrades'] = 'Number of grades'; $string['onascaleof'] = 'on a scale of {$a->grademin} to {$a->grademax}'; diff --git a/lib/adminlib.php b/lib/adminlib.php index 37da3db1b7e..e67ebe1d841 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -5200,6 +5200,52 @@ class admin_setting_grade_profilereport extends admin_setting_configselect { } } +/** + * Provides a selection of grade reports to be used for "my grades". + * + * @copyright 2015 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class admin_setting_my_grades_report extends admin_setting_configselect { + + /** + * Calls parent::__construct with specific arguments. + */ + public function __construct() { + parent::__construct('grade_mygrades_report', new lang_string('mygrades', 'grades'), + new lang_string('mygrades_desc', 'grades'), 'overview', null); + } + + /** + * Loads an array of choices for the configselect control. + * + * @return bool always returns true. + */ + public function load_choices() { + global $CFG; // Remove this line and behold the horror of behat test failures! + $this->choices = array(); + foreach (core_component::get_plugin_list('gradereport') as $plugin => $plugindir) { + if (file_exists($plugindir . '/lib.php')) { + require_once($plugindir . '/lib.php'); + // Check to see if the class exists. Check the correct plugin convention first. + if (class_exists('gradereport_' . $plugin)) { + $classname = 'gradereport_' . $plugin; + } else if (class_exists('grade_report_' . $plugin)) { + // We are using the old plugin naming convention. + $classname = 'grade_report_' . $plugin; + } else { + continue; + } + if ($classname::supports_mygrades()) { + $this->choices[$plugin] = get_string('pluginname', 'gradereport_' . $plugin); + } + } + } + // Add an option to specify an external url. + $this->choices['external'] = get_string('externalurl', 'grades'); + return true; + } +} /** * Special class for register auth selection diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 5ee7f94db36..8bd10313382 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -4304,5 +4304,13 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2015040700.01); } + if ($oldversion < 2015040800.01) { + // Add "My grades" to the user menu. + $newconfig = "mygrades,grades|/grade/report/mygrades.php|grades\n" . $CFG->customusermenuitems; + set_config('customusermenuitems', $newconfig); + + upgrade_main_savepoint(true, 2015040800.01); + } + return true; } diff --git a/lib/navigationlib.php b/lib/navigationlib.php index 3dafc2b20e2..431be6a10b4 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -2267,6 +2267,22 @@ class global_navigation extends navigation_node { $usernode->add(get_string('notes', 'notes'), $url); } + // Show the my grades node. + if (($issitecourse && $iscurrentuser) || has_capability('moodle/user:viewdetails', $usercontext)) { + require_once($CFG->dirroot . '/user/lib.php'); + // Set the grades node to link to the "My grades" page. + if ($course->id == SITEID) { + $url = user_mygrades_url($user->id, $course->id); + } else { // Otherwise we are in a course and should redirect to the user grade report (Activity report version). + $url = new moodle_url('/course/user.php', array('mode' => 'grade', 'id' => $course->id, 'user' => $user->id)); + } + if ($USER->id != $user->id) { + $usernode->add(get_string('grades', 'grades'), $url); + } else { + $usernode->add(get_string('mygrades', 'grades'), $url); + } + } + // If the user is the current user add the repositories for the current user $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); if ($iscurrentuser) { @@ -3804,18 +3820,6 @@ class settings_navigation extends navigation_node { $reportavailable = false; if (has_capability('moodle/grade:viewall', $coursecontext)) { $reportavailable = true; - } else if (!empty($course->showgrades)) { - $reports = core_component::get_plugin_list('gradereport'); - if (is_array($reports) && count($reports)>0) { // Get all installed reports - arsort($reports); // user is last, we want to test it first - foreach ($reports as $plugin => $plugindir) { - if (has_capability('gradereport/'.$plugin.':view', $coursecontext)) { - //stop when the first visible plugin is found - $reportavailable = true; - break; - } - } - } } if ($reportavailable) { $url = new moodle_url('/grade/report/index.php', array('id'=>$course->id)); @@ -4324,30 +4328,7 @@ class settings_navigation extends navigation_node { foreach ($reports as $reportfunction) { $reportfunction($reporttab, $user, $course); } - $anyreport = has_capability('moodle/user:viewuseractivitiesreport', $usercontext); - if ($anyreport || ($course->showreports && $currentuser)) { - // Add grade hardcoded grade report if necessary. - $gradeaccess = false; - if (has_capability('moodle/grade:viewall', $coursecontext)) { - // Can view all course grades. - $gradeaccess = true; - } else if ($course->showgrades) { - if ($currentuser && has_capability('moodle/grade:view', $coursecontext)) { - // Can view own grades. - $gradeaccess = true; - } else if (has_capability('moodle/grade:viewall', $usercontext)) { - // Can view grades of this user - parent most probably. - $gradeaccess = true; - } else if ($anyreport) { - // Can view grades of this user - parent most probably. - $gradeaccess = true; - } - } - if ($gradeaccess) { - $reporttab->add(get_string('grade'), new moodle_url('/course/user.php', array('mode'=>'grade', 'id'=>$course->id, - 'user'=>$usercontext->instanceid))); - } - } + // Check the number of nodes in the report node... if there are none remove the node $reporttab->trim_if_empty(); diff --git a/user/lib.php b/user/lib.php index 8e3dbab2ef8..296da8e64e6 100644 --- a/user/lib.php +++ b/user/lib.php @@ -674,6 +674,11 @@ function user_convert_text_to_menu_items($text, $page) { $bits[1] = null; $child->itemtype = "invalid"; } else { + // Nasty hack to replace the my grades with the direct url. + if (strpos($bits[1], '/grade/report/mygrades.php') !== false) { + $bits[1] = user_mygrades_url(); + } + // Make sure the url is a moodle url. $bits[1] = new moodle_url(trim($bits[1])); } @@ -1023,3 +1028,30 @@ function user_list_view($course, $context) { )); $event->trigger(); } + +/** + * Returns the url to use for the "My grades" link in the user navigation. + * + * @param int $userid The user's ID. + * @param int $courseid The course ID if available. + * @return mixed A URL to be directed to for "My grades". + */ +function user_mygrades_url($userid = null, $courseid = SITEID) { + global $CFG, $USER; + $url = null; + if (isset($CFG->grade_mygrades_report) && $CFG->grade_mygrades_report != 'external') { + if (isset($userid) && $USER->id != $userid) { + // Send to the gradebook report. + $url = new moodle_url('/grade/report/' . $CFG->grade_mygrades_report . '/index.php', + array('id' => $courseid, 'userid' => $userid)); + } else { + $url = new moodle_url('/grade/report/' . $CFG->grade_mygrades_report . '/index.php'); + } + } else if (isset($CFG->grade_mygrades_report) && $CFG->grade_mygrades_report == 'external' + && !empty($CFG->gradereport_mygradeurl)) { + $url = $CFG->gradereport_mygradeurl; + } else { + $url = $CFG->wwwroot; + } + return $url; +}