Merge branch 'MDL-50026' of git://github.com/timhunt/moodle
authorDavid Monllao <davidm@moodle.com>
Wed, 29 Apr 2015 05:25:02 +0000 (13:25 +0800)
committerDavid Monllao <davidm@moodle.com>
Wed, 29 Apr 2015 05:25:02 +0000 (13:25 +0800)
course/user.php
grade/report/user/lib.php
lib/navigationlib.php
lib/pagelib.php
lib/tests/moodlelib_test.php
lib/upgrade.txt
mod/assign/locallib.php
mod/assign/tests/behat/steps_blind_marking.feature [new file with mode: 0644]
report/stats/lib.php
report/stats/user.php
report/usersessions/user.php

index 553267d..a39a622 100644 (file)
@@ -146,14 +146,19 @@ switch ($mode) {
             $url = new moodle_url('/course/user.php', array('id' => $id, 'user' => $user->id, 'mode' => $mode));
             $reportnode = $activenode->add(get_string('pluginname', 'gradereport_user'), $url);
         } else {
+            if ($course->id == SITEID) {
+                $activenode = $PAGE->navigation->find('user' . $user->id, null);
+            } else {
+                $currentcoursenode = $PAGE->navigation->find('currentcourse', null);
+                $activenode = $currentcoursenode->find_active_node();
+            }
             // Check to see if the active node is a user name.
-            $currentcoursenode = $PAGE->navigation->find('currentcourse', null);
-            $activenode = $currentcoursenode->find_active_node();
-            if (strpos($activenode->key, 'user') === false) { // No user name found.
+            if (!preg_match('/^user\d{0,}$/', $activenode->key)) { // No user name found.
                 $userurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $course->id));
                 // Add the user name.
                 $PAGE->navbar->add(fullname($user), $userurl, navigation_node::TYPE_SETTING);
             }
+            $PAGE->navbar->add(get_string('report'));
             $gradeurl = new moodle_url('/course/user.php', array('id' => $id, 'user' => $user->id, 'mode' => $mode));
             // Add the 'grades' node to the navbar.
             $navbar = $PAGE->navbar->add(get_string('grades', 'grades'), $gradeurl, navigation_node::TYPE_SETTING);
index c351800..49cb1a9 100644 (file)
@@ -1171,4 +1171,47 @@ function grade_report_user_profilereport($course, $user, $viewasuser = false) {
     }
 }
 
-
+/**
+ * Add nodes to myprofile page.
+ *
+ * @param \core_user\output\myprofile\tree $tree Tree object
+ * @param stdClass $user user object
+ * @param bool $iscurrentuser
+ * @param stdClass $course Course object
+ */
+function gradereport_user_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) {
+    global $CFG, $USER;
+    if (empty($course)) {
+        // We want to display these reports under the site context.
+        $course = get_fast_modinfo(SITEID)->get_course();
+    }
+    $usercontext = context_user::instance($user->id);
+    $anyreport = has_capability('moodle/user:viewuseractivitiesreport', $usercontext);
+
+    // Start capability checks.
+    if ($anyreport || ($course->showreports && $user->id == $USER->id)) {
+        // Add grade hardcoded grade report if necessary.
+        $gradeaccess = false;
+        $coursecontext = context_course::instance($course->id);
+        if (has_capability('moodle/grade:viewall', $coursecontext)) {
+            // Can view all course grades.
+            $gradeaccess = true;
+        } else if ($course->showgrades) {
+            if ($iscurrentuser && 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) {
+            $url = new moodle_url('/course/user.php', array('mode' => 'grade', 'id' => $course->id, 'user' => $user->id));
+            $node = new core_user\output\myprofile\node('reports', 'grade', get_string('grade'), null, $url);
+            $tree->add_node($node);
+        }
+    }
+}
index f0163cd..54bc395 100644 (file)
@@ -4220,7 +4220,7 @@ class settings_navigation extends navigation_node {
 
             // Add the user profile to the dashboard.
             $profilenode = $dashboard->add(get_string('myprofile'), new moodle_url('/user/profile.php',
-                    array('id' => $user->id)), null, 'myprofile');
+                    array('id' => $user->id)), self::TYPE_SETTING, null, 'myprofile');
 
             if (!empty($CFG->navadduserpostslinks)) {
                 // Add nodes for forum posts and discussions if the user can view either or both
index 8f66ba5..0c0e99b 100644 (file)
@@ -1927,4 +1927,40 @@ class moodle_page {
         }
         return $region;
     }
+
+    /**
+     * Add a report node and a specific report to the navigation.
+     *
+     * @param int $userid The user ID that we are looking to add this report node to.
+     * @param array $nodeinfo Name and url of the final node that we are creating.
+     */
+    public function add_report_nodes($userid, $nodeinfo) {
+        global $USER;
+        // Try to find the specific user node.
+        $newusernode = $this->navigation->find('user' . $userid, null);
+        $reportnode = null;
+        $navigationnodeerror =
+                'Could not find the navigation node requested. Please check that the node you are looking for exists.';
+        if ($userid != $USER->id) {
+            // Check that we have a valid node.
+            if (empty($newusernode)) {
+                // Throw an error if we ever reach here.
+                throw new coding_exception($navigationnodeerror);
+            }
+            // Add 'Reports' to the user node.
+            $reportnode = $newusernode->add(get_string('reports'));
+        } else {
+            // We are looking at our own profile.
+            $myprofilenode = $this->settingsnav->find('myprofile', null);
+            // Check that we do end up with a valid node.
+            if (empty($myprofilenode)) {
+                // Throw an error if we ever reach here.
+                throw new coding_exception($navigationnodeerror);
+            }
+            // Add 'Reports' to our node.
+            $reportnode = $myprofilenode->add(get_string('reports'));
+        }
+        // Finally add the report to the navigation tree.
+        $reportnode->add($nodeinfo['name'], $nodeinfo['url'], navigation_node::TYPE_COURSE);
+    }
 }
index ce944fa..54b08df 100644 (file)
@@ -1364,70 +1364,70 @@ class core_moodlelib_testcase extends advanced_testcase {
         // DST switching in Prague.
         // From 2AM to 3AM in 1989.
         $date = new DateTime('1989-03-26T01:59:00+01:00');
-        $this->assertSame('Sunday, 26 March 1989, 1:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 26 March 1989, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         $date = new DateTime('1989-03-26T02:01:00+01:00');
-        $this->assertSame('Sunday, 26 March 1989, 3:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 26 March 1989, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         // From 3AM to 2AM in 1989 - not the same as the west Europe.
         $date = new DateTime('1989-09-24T01:59:00+01:00');
-        $this->assertSame('Sunday, 24 September 1989, 2:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 24 September 1989, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         $date = new DateTime('1989-09-24T02:01:00+01:00');
-        $this->assertSame('Sunday, 24 September 1989, 2:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 24 September 1989, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         // From 2AM to 3AM in 2014.
         $date = new DateTime('2014-03-30T01:59:00+01:00');
-        $this->assertSame('Sunday, 30 March 2014, 1:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 30 March 2014, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         $date = new DateTime('2014-03-30T02:01:00+01:00');
-        $this->assertSame('Sunday, 30 March 2014, 3:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 30 March 2014, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         // From 3AM to 2AM in 2014.
         $date = new DateTime('2014-10-26T01:59:00+01:00');
-        $this->assertSame('Sunday, 26 October 2014, 2:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 26 October 2014, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         $date = new DateTime('2014-10-26T02:01:00+01:00');
-        $this->assertSame('Sunday, 26 October 2014, 2:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 26 October 2014, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         // From 2AM to 3AM in 2020.
         $date = new DateTime('2020-03-29T01:59:00+01:00');
-        $this->assertSame('Sunday, 29 March 2020, 1:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 29 March 2020, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         $date = new DateTime('2020-03-29T02:01:00+01:00');
-        $this->assertSame('Sunday, 29 March 2020, 3:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 29 March 2020, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         // From 3AM to 2AM in 2020.
         $date = new DateTime('2020-10-25T01:59:00+01:00');
-        $this->assertSame('Sunday, 25 October 2020, 2:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 25 October 2020, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
         $date = new DateTime('2020-10-25T02:01:00+01:00');
-        $this->assertSame('Sunday, 25 October 2020, 2:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Europe/Prague'));
+        $this->assertSame('Sunday, 25 October 2020, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague'));
 
         // DST switching in NZ.
         // From 3AM to 2AM in 2015.
         $date = new DateTime('2015-04-05T02:59:00+13:00');
-        $this->assertSame('Sunday, 5 April 2015, 2:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Pacific/Auckland'));
+        $this->assertSame('Sunday, 5 April 2015, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland'));
         $date = new DateTime('2015-04-05T03:01:00+13:00');
-        $this->assertSame('Sunday, 5 April 2015, 2:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Pacific/Auckland'));
+        $this->assertSame('Sunday, 5 April 2015, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland'));
         // From 2AM to 3AM in 2009.
         $date = new DateTime('2015-09-27T01:59:00+12:00');
-        $this->assertSame('Sunday, 27 September 2015, 1:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Pacific/Auckland'));
+        $this->assertSame('Sunday, 27 September 2015, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland'));
         $date = new DateTime('2015-09-27T02:01:00+12:00');
-        $this->assertSame('Sunday, 27 September 2015, 3:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Pacific/Auckland'));
+        $this->assertSame('Sunday, 27 September 2015, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland'));
 
         // DST switching in Perth.
         // From 3AM to 2AM in 2009.
         $date = new DateTime('2008-03-30T01:59:00+08:00');
-        $this->assertSame('Sunday, 30 March 2008, 2:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Australia/Perth'));
+        $this->assertSame('Sunday, 30 March 2008, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth'));
         $date = new DateTime('2008-03-30T02:01:00+08:00');
-        $this->assertSame('Sunday, 30 March 2008, 2:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Australia/Perth'));
+        $this->assertSame('Sunday, 30 March 2008, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth'));
         // From 2AM to 3AM in 2009.
         $date = new DateTime('2008-10-26T01:59:00+08:00');
-        $this->assertSame('Sunday, 26 October 2008, 1:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Australia/Perth'));
+        $this->assertSame('Sunday, 26 October 2008, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth'));
         $date = new DateTime('2008-10-26T02:01:00+08:00');
-        $this->assertSame('Sunday, 26 October 2008, 3:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'Australia/Perth'));
+        $this->assertSame('Sunday, 26 October 2008, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth'));
 
         // DST switching in US.
         // From 2AM to 3AM in 2014.
         $date = new DateTime('2014-03-09T01:59:00-05:00');
-        $this->assertSame('Sunday, 9 March 2014, 1:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'America/New_York'));
+        $this->assertSame('Sunday, 9 March 2014, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York'));
         $date = new DateTime('2014-03-09T02:01:00-05:00');
-        $this->assertSame('Sunday, 9 March 2014, 3:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'America/New_York'));
+        $this->assertSame('Sunday, 9 March 2014, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York'));
         // From 3AM to 2AM in 2014.
         $date = new DateTime('2014-11-02T01:59:00-04:00');
-        $this->assertSame('Sunday, 2 November 2014, 1:59', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'America/New_York'));
+        $this->assertSame('Sunday, 2 November 2014, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York'));
         $date = new DateTime('2014-11-02T02:01:00-04:00');
-        $this->assertSame('Sunday, 2 November 2014, 1:01', userdate($date->getTimestamp(), '%A, %d %B %Y,%k:%M', 'America/New_York'));
+        $this->assertSame('Sunday, 2 November 2014, 01:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York'));
     }
 
     public function test_make_timestamp() {
index bc4d1e5..834f3fc 100644 (file)
@@ -39,6 +39,9 @@ information provided here is intended especially for developers.
 * The outdated lib/google/Google_Client.php and related files have been completely removed. To use
   the new client, read lib/google/readme_moodle.txt, please.
 * profile_display_badges() has been deprecated. See MDL-48935 for details.
+* Added a new method add_report_nodes() to pagelib.php. If you are looking to add links to the user profile page under the heading "Reports"
+  then please use this function to ensure that the breadcrumb and navigation block are created properly for all user profile pages.
+
 
 === 2.8 ===
 
index d38fa6f..79d509f 100644 (file)
@@ -5503,6 +5503,7 @@ class assign {
 
         $adminconfig = $this->get_admin_config();
         $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
+        $gradebookplugin = str_replace('assignfeedback_', '', $gradebookplugin);
         $grades = $DB->get_records('assign_grades', array('assignment'=>$this->get_instance()->id));
 
         $plugin = $this->get_feedback_plugin_by_type($gradebookplugin);
diff --git a/mod/assign/tests/behat/steps_blind_marking.feature b/mod/assign/tests/behat/steps_blind_marking.feature
new file mode 100644 (file)
index 0000000..3b4d826
--- /dev/null
@@ -0,0 +1,99 @@
+@mod @mod_assign
+Feature: Assignments correctly add feedback to the grade report when workflow and blind marking are enabled.
+  In order to give students feedback when blind marking
+  As a teacher
+  I should be able to reveal student identities at any time and have my feedback show
+  to the student in the gradebook when the grades are in a released state.
+
+  Background:
+    Given the following "courses" exist:
+      | fullname | shortname | category | groupmode |
+      | Course 1 | C1 | 0 | 1 |
+    And the following "users" exist:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@example.com |
+      | student1 | Student | 1 | student1@example.com |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+    # Add the assignment.
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment name |
+      | Description | Test assignment description |
+      | Online text | 1 |
+      | File submissions | 0 |
+      | Use marking workflow | Yes |
+      | Blind marking | Yes |
+    And I log out
+    # Add a submission.
+    And I log in as "student1"
+    And I follow "Course 1"
+    When I follow "Test assignment name"
+    Then I should not see "Feedback"
+    And I should see "Not marked" in the "Grading status" "table_row"
+    And I press "Add submission"
+    And I set the following fields to these values:
+      | Online text | I'm the student's first submission |
+    And I press "Save changes"
+    And I log out
+    # Mark the submission.
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I follow "Test assignment name"
+    And I follow "View/grade all submissions"
+    And I should see "Not marked" in the "Participant 1" "table_row"
+    And I click on "Grade Participant 1" "link" in the "Participant 1" "table_row"
+    And I set the field "Grade out of 100" to "50"
+    And I set the field "Marking workflow state" to "In review"
+    And I set the field "Feedback comments" to "Great job! Lol, not really."
+    And I press "Save changes"
+    And I press "Continue"
+    And I should see "In review" in the "Participant 1" "table_row"
+
+  @javascript
+  Scenario: Student identities are revealed after releasing the grades.
+    When I click on "Grade Participant 1" "link" in the "Participant 1" "table_row"
+    And I set the field "Marking workflow state" to "Ready for release"
+    And I press "Save changes"
+    And I press "Continue"
+    And I should see "Ready for release" in the "Participant 1" "table_row"
+    And I click on "Grade Participant 1" "link" in the "Participant 1" "table_row"
+    And I set the field "Marking workflow state" to "Released"
+    And I press "Save changes"
+    And I press "Continue"
+    And I should see "Released" in the "Participant 1" "table_row"
+    And I set the field "Grading action" to "Reveal student identities"
+    And I press "Continue"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Grades"
+    And I set the field "Grade report" to "User report"
+    Then I should see "50"
+    And I should see "Great job! Lol, not really."
+
+  @javascript
+  Scenario: Student identities are revealed before releasing the grades.
+    When I click on "Grade Participant 1" "link" in the "Participant 1" "table_row"
+    And I set the field "Marking workflow state" to "Ready for release"
+    And I press "Save changes"
+    And I press "Continue"
+    And I should see "Ready for release" in the "Participant 1" "table_row"
+    And I set the field "Grading action" to "Reveal student identities"
+    And I press "Continue"
+    And I click on "Grade Student 1" "link" in the "Student 1" "table_row"
+    And I set the field "Marking workflow state" to "Released"
+    And I press "Save changes"
+    And I press "Continue"
+    And I should see "Released" in the "Student 1" "table_row"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Grades"
+    And I set the field "Grade report" to "User report"
+    Then I should see "50"
+    And I should see "Great job! Lol, not really."
index ac9fc4d..f0a069b 100644 (file)
@@ -127,3 +127,28 @@ function report_stats_supports_logstore($instance) {
     }
     return false;
 }
+
+/**
+ * Add nodes to myprofile page.
+ *
+ * @param \core_user\output\myprofile\tree $tree Tree object
+ * @param stdClass $user user object
+ * @param bool $iscurrentuser
+ * @param stdClass $course Course object
+ * @return bool
+ */
+function report_stats_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) {
+    global $CFG;
+    if (empty($CFG->enablestats)) {
+        return false;
+    }
+    if (empty($course)) {
+        // We want to display these reports under the site context.
+        $course = get_fast_modinfo(SITEID)->get_course();
+    }
+    if (report_stats_can_access_user_report($user, $course)) {
+        $url = new moodle_url('/report/stats/user.php', array('id' => $user->id, 'course' => $course->id));
+        $node = new core_user\output\myprofile\node('reports', 'stats', get_string('stats'), null, $url);
+        $tree->add_node($node);
+    }
+}
index 42360c3..48e151d 100644 (file)
@@ -35,6 +35,13 @@ $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
 $coursecontext   = context_course::instance($course->id);
 $personalcontext = context_user::instance($user->id);
 
+$pageheading = $course->fullname;
+$userfullname = fullname($user);
+if ($courseid == SITEID) {
+    $PAGE->set_context($personalcontext);
+    $pageheading = $userfullname;
+}
+
 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!
@@ -55,9 +62,24 @@ $PAGE->set_pagelayout('report');
 $PAGE->set_url('/report/stats/user.php', array('id'=>$user->id, 'course'=>$course->id));
 $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.
+// Breadcrumb stuff.
+$navigationnode = array(
+        'name' => get_string('stats'),
+        'url' => new moodle_url('/report/stats/user.php', array('id' => $user->id, 'course' => $course->id))
+    );
+$PAGE->add_report_nodes($user->id, $navigationnode);
+
 $PAGE->set_title("$course->shortname: $stractivityreport");
-$PAGE->set_heading($course->fullname);
+$PAGE->set_heading($pageheading);
 echo $OUTPUT->header();
+if ($courseid != SITEID) {
+    echo $OUTPUT->context_header(
+            array(
+            'heading' => $userfullname,
+            'user' => $user,
+            'usercontext' => $personalcontext
+        ), 2);
+}
 
 // Trigger a user report viewed event.
 $event = \report_stats\event\user_report_viewed::create(array('context' => $coursecontext, 'relateduserid' => $user->id));
index 7c91197..52e2d85 100644 (file)
@@ -55,6 +55,12 @@ if ($delete and confirm_sesskey()) {
     redirect($PAGE->url);
 }
 
+// Create the breadcrumb.
+$PAGE->add_report_nodes($USER->id, array(
+        'name' => get_string('navigationlink', 'report_usersessions'),
+        'url' => new moodle_url('/report/usersessions/user.php')
+    ));
+
 echo $OUTPUT->header();
 echo $OUTPUT->heading(get_string('mysessions', 'report_usersessions'));