Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace core_grades;
  18  
  19  use grade_plugin_return;
  20  use gradereport_user\report\user as user_report;
  21  
  22  defined('MOODLE_INTERNAL') || die();
  23  
  24  global $CFG;
  25  require_once($CFG->dirroot.'/grade/lib.php');
  26  require_once($CFG->dirroot.'/grade/report/user/lib.php');
  27  
  28  /**
  29   * Tests grade_report_user (the gradebook's user report)
  30   *
  31   * @package  core_grades
  32   * @category test
  33   * @copyright 2012 Andrew Davis
  34   * @license  http://www.gnu.org/copyleft/gpl.html GNU Public License
  35   */
  36  class reportuserlib_test extends \advanced_testcase {
  37  
  38      /**
  39       * Tests grade_report_user::inject_rowspans()
  40       *
  41       * inject_rowspans() returns the count of the number of elements, sets maxdepth on the
  42       *  report object and sets the rowspan property on any element that has children.
  43       */
  44      public function test_inject_rowspans() {
  45          global $CFG, $USER, $DB;
  46  
  47          parent::setUp();
  48          $this->resetAfterTest(true);
  49  
  50          $CFG->enableavailability = 1;
  51          $CFG->enablecompletion = 1;
  52  
  53          // Create a course.
  54          $course = $this->getDataGenerator()->create_course();
  55          $coursecategory = \grade_category::fetch_course_category($course->id);
  56          $coursecontext = \context_course::instance($course->id);
  57  
  58          // Create and enrol test users.
  59          $student = $this->getDataGenerator()->create_user(array('username' => 'student_sam'));
  60          $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
  61          $this->getDataGenerator()->enrol_user($student->id, $course->id, $role->id);
  62  
  63          $teacher = $this->getDataGenerator()->create_user(array('username' => 'teacher_t'));
  64          $role = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST);
  65          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $role->id);
  66  
  67          // An array so we can test with both users in a loop.
  68          $users = array($student, $teacher);
  69  
  70          // Make the student the current user.
  71          $this->setUser($student);
  72  
  73          // Test an empty course.
  74          $report = $this->create_report($course, $student, $coursecontext);
  75          // a lead column that spans all children + course grade item = 2
  76          $this->assertEquals(2, $report->inject_rowspans($report->gtree->top_element));
  77          $this->assertEquals(2, $report->gtree->top_element['rowspan']);
  78          $this->assertEquals(2, $report->maxdepth);
  79  
  80          // Only elements with children should have rowspan set.
  81          if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) {
  82              $this->fail('Elements without children should not have rowspan set');
  83          }
  84  
  85          // Add 2 activities.
  86          $data1 = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
  87  
  88          $forum1 = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
  89          $forum1cm = get_coursemodule_from_id('forum', $forum1->cmid);
  90          // Switch the stdClass instance for a grade item instance so \grade_item::set_parent() is available.
  91          $forum1 = \grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum1->id, 'courseid' => $course->id));
  92  
  93          $report = $this->create_report($course, $student, $coursecontext);
  94          // Lead column + course + (2 x activity) = 4
  95          $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element));
  96          $this->assertEquals(4, $report->gtree->top_element['rowspan']);
  97          // Lead column + 1 level (course + 2 activities) = 2
  98          $this->assertEquals(2, $report->maxdepth);
  99  
 100          // Only elements with children should have rowspan set.
 101          if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) {
 102              $this->fail('Elements without children should not have rowspan set');
 103          }
 104  
 105          // Hide the forum activity.
 106          set_coursemodule_visible($forum1cm->id, 0);
 107  
 108          foreach ($users as $user) {
 109  
 110              $this->setUser($user);
 111              $message = 'Testing with ' . $user->username;
 112              accesslib_clear_all_caches_for_unit_testing();
 113  
 114              $report = $this->create_report($course, $user, $coursecontext);
 115              // Lead column + course + (2 x activity) = 4 (element count isn't affected by hiding)
 116              $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element), $message);
 117              $this->assertEquals(4, $report->gtree->top_element['rowspan'], $message);
 118              // Lead column -> 1 level containing the course + 2 activities = 2
 119              $this->assertEquals(2, $report->maxdepth, $message);
 120          }
 121  
 122          // Unhide the forum activity.
 123          set_coursemodule_visible($forum1cm->id, 1);
 124  
 125          // Create a category and put the forum in it.
 126          $params = new \stdClass();
 127          $params->courseid = $course->id;
 128          $params->fullname = 'unittestcategory';
 129          $params->parent = $coursecategory->id;
 130          $gradecategory = new \grade_category($params, false);
 131          $gradecategory->insert();
 132  
 133          $forum1->set_parent($gradecategory->id);
 134  
 135          $report = $this->create_report($course, $student, $coursecontext);
 136          // Lead column + course + (category + lead column + category grade item) + (2 x activity) = 7.
 137          $this->assertEquals(7, $report->inject_rowspans($report->gtree->top_element));
 138          $this->assertEquals(7, $report->gtree->top_element['rowspan']);
 139          // Lead column -> the category -> the forum activity = 3
 140          $this->assertEquals(3, $report->maxdepth);
 141  
 142          // Check rowspan on the category. The category itself + category grade item + forum = 3
 143          $this->assertEquals(3, $report->gtree->top_element['children'][4]['rowspan']);
 144          // check the forum doesn't have rowspan set
 145          if (array_key_exists('rowspan', $report->gtree->top_element['children'][4]['children'][3])) {
 146              $this->fail('The forum has no children so should not have rowspan set');
 147          }
 148  
 149          // Conditional activity tests.
 150          // Note: I have ported this test to the new conditional availability
 151          // system, but it does not appear to actually test anything - in fact,
 152          // if you remove the code that sets the condition, it still passes
 153          // because it apparently is intended to have the same number of rows
 154          // even when some are hidden. The  same is true of the
 155          // set_coursemodule_visible test above. I don't feel this is a very
 156          // good test; somebody with more knowledge of this report might want to
 157          // fix it to check that the row actually is being hidden.
 158          $DB->set_field('course_modules', 'availability', '{"op":"|","show":false,"c":[' .
 159                  '{"type":"grade","min":5.5,"id":37}]}', array('id' => $forum1cm->id));
 160          get_fast_modinfo($course->id, 0, true);
 161          foreach ($users as $user) {
 162  
 163              $this->setUser($user);
 164              $message = 'Testing with ' . $user->username;
 165              accesslib_clear_all_caches_for_unit_testing();
 166  
 167              $report = $this->create_report($course, $user, $coursecontext);
 168              // Lead column + course + (category + lead column + category grade item) + (2 x activity) = 7.
 169              $this->assertEquals(7, $report->inject_rowspans($report->gtree->top_element), $message);
 170              $this->assertEquals(7, $report->gtree->top_element['rowspan'], $message);
 171              // Lead column -> the category -> the forum activity = 3
 172              $this->assertEquals(3, $report->maxdepth, $message);
 173          }
 174      }
 175  
 176      private function create_report($course, $user, $coursecontext) {
 177  
 178          $gpr = new grade_plugin_return(array('type' => 'report', 'plugin'=>'user', 'courseid' => $course->id, 'userid' => $user->id));
 179          $report = new user_report($course->id, $gpr, $coursecontext, $user->id);
 180  
 181          return $report;
 182      }
 183  
 184  }
 185