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.
   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  /**
  18   * Tests for the the Forum gradeitem.
  19   *
  20   * @package    mod_forum
  21   * @copyright Andrew Nicols <andrew@nicols.co.uk>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace mod_forum\grade;
  26  
  27  use core_grades\component_gradeitem;
  28  use mod_forum\grades\forum_gradeitem as gradeitem;
  29  use mod_forum\local\entities\forum as forum_entity;
  30  use gradingform_controller;
  31  use mod_forum\grades\forum_gradeitem;
  32  
  33  defined('MOODLE_INTERNAL') || die();
  34  
  35  require_once (__DIR__ . '/../generator_trait.php');
  36  
  37  /**
  38   * Tests for the the Forum gradeitem.
  39   *
  40   * @package    mod_forum
  41   * @copyright Andrew Nicols <andrew@nicols.co.uk>
  42   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  43   */
  44  class forum_gradeitem_test extends \advanced_testcase {
  45      use \mod_forum_tests_generator_trait;
  46  
  47      /**
  48       * Test fetching of a grade for a user when the grade has been created.
  49       */
  50      public function test_get_grade_for_user_exists(): void {
  51          $forum = $this->get_forum_instance([
  52              'grade_forum' => 0,
  53          ]);
  54          $course = $forum->get_course_record();
  55          [$student] = $this->helper_create_users($course, 1);
  56          [$grader] = $this->helper_create_users($course, 1, 'editingteacher');
  57  
  58          $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
  59  
  60          // Create the grade record.
  61          $grade = $gradeitem->create_empty_grade($student, $grader);
  62  
  63          $this->assertIsObject($grade);
  64          $this->assertEquals($student->id, $grade->userid);
  65      }
  66  
  67      /**
  68       * Test fetching of a grade for a user when the grade has been created.
  69       */
  70      public function test_user_has_grade(): void {
  71          $forum = $this->get_forum_instance([
  72              'grade_forum' => 100,
  73          ]);
  74          $course = $forum->get_course_record();
  75          [$student] = $this->helper_create_users($course, 1);
  76          [$grader] = $this->helper_create_users($course, 1, 'editingteacher');
  77  
  78          $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
  79  
  80          $hasgrade = $gradeitem->user_has_grade($student);
  81          $this->assertEquals(false, $hasgrade);
  82          // Create the grade record.
  83          $gradeitem->create_empty_grade($student, $grader);
  84  
  85          $hasgrade = $gradeitem->user_has_grade($student);
  86          $this->assertEquals(false, $hasgrade);
  87  
  88          // Store a new value.
  89          $gradeitem->store_grade_from_formdata($student, $grader, (object) ['grade' => 97]);
  90          $hasgrade = $gradeitem->user_has_grade($student);
  91          $this->assertEquals(true, $hasgrade);
  92      }
  93  
  94      /**
  95       * Ensure that it is possible to get, and update, a grade for a user when simple direct grading is in use.
  96       */
  97      public function test_get_and_store_grade_for_user_with_simple_direct_grade(): void {
  98          $forum = $this->get_forum_instance([
  99              'grade_forum' => 100,
 100          ]);
 101          $course = $forum->get_course_record();
 102          [$student] = $this->helper_create_users($course, 1);
 103          [$grader] = $this->helper_create_users($course, 1, 'editingteacher');
 104  
 105          $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
 106  
 107          // Create the grade record.
 108          $grade = $gradeitem->create_empty_grade($student, $grader);
 109  
 110          $this->assertIsObject($grade);
 111          $this->assertEquals($student->id, $grade->userid);
 112  
 113          // Store a new value.
 114          $gradeitem->store_grade_from_formdata($student, $grader, (object) ['grade' => 97]);
 115      }
 116  
 117      /**
 118       * Ensure that it is possible to get, and update, a grade for a user when a rubric is in use.
 119       */
 120      public function test_get_and_store_grade_for_user_with_rubric(): void {
 121          global $DB;
 122  
 123          $this->resetAfterTest();
 124  
 125          $generator = \testing_util::get_data_generator();
 126          $gradinggenerator = $generator->get_plugin_generator('core_grading');
 127          $rubricgenerator = $generator->get_plugin_generator('gradingform_rubric');
 128  
 129          $forum = $this->get_forum_instance([
 130              'grade_forum' => 100,
 131          ]);
 132          $course = $forum->get_course_record();
 133          $context = $forum->get_context();
 134          [$student] = $this->helper_create_users($course, 1);
 135          [$grader] = $this->helper_create_users($course, 1, 'editingteacher');
 136          [$editor] = $this->helper_create_users($course, 1, 'editingteacher');
 137  
 138          // Note: This must be run as a user because it messes with file uploads and drafts.
 139          $this->setUser($editor);
 140  
 141          $controller = $rubricgenerator->get_test_rubric($context, 'mod_forum', 'forum');
 142  
 143          // Create the forum_gradeitem object that we'll be testing.
 144          $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
 145  
 146          // The current grade should be null initially.
 147          $this->assertCount(0, $DB->get_records('forum_grades'));
 148          $grade = $gradeitem->get_grade_for_user($student, $grader);
 149          $instance = $gradeitem->get_advanced_grading_instance($grader, $grade);
 150  
 151          $this->assertIsObject($grade);
 152          $this->assertEquals($student->id, $grade->userid);
 153          $this->assertEquals($forum->get_id(), $grade->forum);
 154  
 155          $rubricgenerator = $generator->get_plugin_generator('gradingform_rubric');
 156          $data = $rubricgenerator->get_submitted_form_data($controller, $grade->id, [
 157              'Spelling is important' => [
 158                  'score' => 2,
 159                  'remark' => 'Abracadabra',
 160              ],
 161              'Pictures' => [
 162                  'score' => 1,
 163                  'remark' => 'More than one picture',
 164              ],
 165          ]);
 166  
 167          // Store a new value.
 168          $gradeitem->store_grade_from_formdata($student, $grader, (object) [
 169              'instanceid' => $instance->get_id(),
 170              'advancedgrading' => $data,
 171          ]);
 172      }
 173  
 174      /**
 175       * Test the logic in the should_grade_only_active_users() method.
 176       *
 177       * @covers ::should_grade_only_active_users
 178       * @dataProvider should_grade_only_active_users_provider
 179       * @param bool $showonlyactiveenrolconfig Whether the 'grade_report_showonlyactiveenrol' is enabled or not.
 180       * @param bool $showonlyactiveenrolpreference Whether the 'grade_report_showonlyactiveenrol' preference is enabled or not.
 181       * @param bool $viewsuspendeduserscapability Whether the 'moodle/course:viewsuspendedusers' capability is allowed or not.
 182       * @param bool $expected The expected result.
 183       */
 184      public function test_should_grade_only_active_users(bool $showonlyactiveenrolconfig, bool $showonlyactiveenrolpreference,
 185              bool $viewsuspendeduserscapability, bool $expected): void {
 186          global $DB;
 187  
 188          $this->resetAfterTest();
 189  
 190          $forum = $this->get_forum_instance([
 191              'grade_forum' => 100,
 192          ]);
 193          $course = $forum->get_course_record();
 194          $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
 195  
 196          $user = $this->getDataGenerator()->create_user();
 197          $this->getDataGenerator()->enrol_user($user->id, $course->id, 'editingteacher');
 198          $editingteacherroleid = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
 199  
 200          // Set the 'grade_report_showonlyactiveenrol' config setting.
 201          set_config('grade_report_showonlyactiveenrol', $showonlyactiveenrolconfig);
 202  
 203          $this->setUser($user);
 204          // Set the 'grade_report_showonlyactiveenrol' user preference.
 205          set_user_preference('grade_report_showonlyactiveenrol', $showonlyactiveenrolpreference);
 206  
 207          // Set the 'moodle/course:viewsuspendedusers' user capability.
 208          assign_capability('moodle/course:viewsuspendedusers', $viewsuspendeduserscapability ?
 209              CAP_ALLOW : CAP_PROHIBIT, $editingteacherroleid, \context_course::instance($course->id));
 210  
 211          $this->assertEquals($expected, $gradeitem->should_grade_only_active_users());
 212      }
 213  
 214      /**
 215       * Data provider for test_should_grade_only_active_users.
 216       *
 217       * @return array
 218       */
 219      public function should_grade_only_active_users_provider(): array {
 220          return [
 221              'Enabled showonlyactiveenrol setting; enabled showonlyactiveenrol preference; view suspended users capability' =>
 222                  [
 223                      'showonlyactiveenrolconfig' => true,
 224                      'showonlyactiveenrolpreference' => true,
 225                      'viewsuspendeduserscapability' => true,
 226                      'expected' => true,
 227                  ],
 228              'Disabled showonlyactiveenrol setting; enabled showonlyactiveenrol preference; view suspended users capability' =>
 229                  [
 230                      'showonlyactiveenrolconfig' => false,
 231                      'showonlyactiveenrolpreference' => true,
 232                      'viewsuspendeduserscapability' => true,
 233                      'expected' => true,
 234                  ],
 235              'Disabled showonlyactiveenrol setting; disabled showonlyactiveenrol preference; view suspended users capability' =>
 236                  [
 237                      'showonlyactiveenrolconfig' => false,
 238                      'showonlyactiveenrolpreference' => false,
 239                      'viewsuspendeduserscapability' => true,
 240                      'expected' => false,
 241                  ],
 242              'Disabled showonlyactiveenrol setting; disabled showonlyactiveenrol preference; no view suspended users capability' =>
 243                  [
 244                      'showonlyactiveenrolconfig' => false,
 245                      'showonlyactiveenrolpreference' => false,
 246                      'viewsuspendeduserscapability' => false,
 247                      'expected' => true,
 248                  ],
 249              'Enabled showonlyactiveenrol setting; enabled showonlyactiveenrol preference; no view suspended users capability' =>
 250                  [
 251                      'showonlyactiveenrolconfig' => true,
 252                      'showonlyactiveenrolpreference' => true,
 253                      'viewsuspendeduserscapability' => false,
 254                      'expected' => true,
 255                  ],
 256          ];
 257      }
 258  
 259      /**
 260       * Get a forum instance.
 261       *
 262       * @param array $config
 263       * @return forum_entity
 264       */
 265      protected function get_forum_instance(array $config = []): forum_entity {
 266          $this->resetAfterTest();
 267  
 268          $datagenerator = $this->getDataGenerator();
 269          $course = $datagenerator->create_course();
 270          $forum = $datagenerator->create_module('forum', array_merge($config, ['course' => $course->id]));
 271  
 272          $vaultfactory = \mod_forum\local\container::get_vault_factory();
 273          $vault = $vaultfactory->get_forum_vault();
 274  
 275          return $vault->get_from_id((int) $forum->id);
 276      }
 277  }