| 1 | efrain | 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 |  * Unit tests for grade/lib.php.
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @package   core_grades
 | 
        
           |  |  | 21 |  * @category  test
 | 
        
           |  |  | 22 |  * @copyright 2016 Jun Pataleta
 | 
        
           |  |  | 23 |  * @license   http://www.gnu.org/copyleft/gpl.html GNU Public License
 | 
        
           |  |  | 24 |  */
 | 
        
           |  |  | 25 | namespace core_grades;
 | 
        
           |  |  | 26 |   | 
        
           |  |  | 27 | use assign;
 | 
        
           |  |  | 28 | use cm_info;
 | 
        
           |  |  | 29 | use grade_item;
 | 
        
           |  |  | 30 | use grade_plugin_return;
 | 
        
           |  |  | 31 | use grade_report_grader;
 | 
        
           |  |  | 32 |   | 
        
           |  |  | 33 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 34 |   | 
        
           |  |  | 35 | global $CFG;
 | 
        
           |  |  | 36 | require_once($CFG->dirroot . '/grade/lib.php');
 | 
        
           |  |  | 37 |   | 
        
           |  |  | 38 | /**
 | 
        
           |  |  | 39 |  * Unit tests for grade/lib.php.
 | 
        
           |  |  | 40 |  *
 | 
        
           |  |  | 41 |  * @package   core_grades
 | 
        
           |  |  | 42 |  * @category  test
 | 
        
           |  |  | 43 |  * @copyright 2016 Jun Pataleta <jun@moodle.com>
 | 
        
           |  |  | 44 |  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 45 |  */
 | 
        
           |  |  | 46 | class lib_test extends \advanced_testcase {
 | 
        
           |  |  | 47 |   | 
        
           |  |  | 48 |     /**
 | 
        
           |  |  | 49 |      * Test can_output_item.
 | 
        
           |  |  | 50 |      */
 | 
        
           | 11 | efrain | 51 |     public function test_can_output_item(): void {
 | 
        
           | 1 | efrain | 52 |         $this->resetAfterTest();
 | 
        
           |  |  | 53 |   | 
        
           |  |  | 54 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 55 |   | 
        
           |  |  | 56 |         // Course level grade category.
 | 
        
           |  |  | 57 |         $course = $generator->create_course();
 | 
        
           |  |  | 58 |         // Grade tree looks something like:
 | 
        
           |  |  | 59 |         // - Test course    (Rendered).
 | 
        
           |  |  | 60 |         $gradetree = \grade_category::fetch_course_tree($course->id);
 | 
        
           |  |  | 61 |         $this->assertTrue(\grade_tree::can_output_item($gradetree));
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 |         // Add a grade category with default settings.
 | 
        
           |  |  | 64 |         $generator->create_grade_category(array('courseid' => $course->id));
 | 
        
           |  |  | 65 |         // Grade tree now looks something like:
 | 
        
           |  |  | 66 |         // - Test course n        (Rendered).
 | 
        
           |  |  | 67 |         // -- Grade category n    (Rendered).
 | 
        
           |  |  | 68 |         $gradetree = \grade_category::fetch_course_tree($course->id);
 | 
        
           |  |  | 69 |         $this->assertNotEmpty($gradetree['children']);
 | 
        
           |  |  | 70 |         foreach ($gradetree['children'] as $child) {
 | 
        
           |  |  | 71 |             $this->assertTrue(\grade_tree::can_output_item($child));
 | 
        
           |  |  | 72 |         }
 | 
        
           |  |  | 73 |   | 
        
           |  |  | 74 |         // Add a grade category with grade type = None.
 | 
        
           |  |  | 75 |         $nototalcategory = 'No total category';
 | 
        
           |  |  | 76 |         $nototalparams = [
 | 
        
           |  |  | 77 |             'courseid' => $course->id,
 | 
        
           |  |  | 78 |             'fullname' => $nototalcategory,
 | 
        
           |  |  | 79 |             'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN
 | 
        
           |  |  | 80 |         ];
 | 
        
           |  |  | 81 |         $nototal = $generator->create_grade_category($nototalparams);
 | 
        
           |  |  | 82 |         $catnototal = \grade_category::fetch(array('id' => $nototal->id));
 | 
        
           |  |  | 83 |         // Set the grade type of the grade item associated to the grade category.
 | 
        
           |  |  | 84 |         $catitemnototal = $catnototal->load_grade_item();
 | 
        
           |  |  | 85 |         $catitemnototal->gradetype = GRADE_TYPE_NONE;
 | 
        
           |  |  | 86 |         $catitemnototal->update();
 | 
        
           |  |  | 87 |   | 
        
           |  |  | 88 |         // Grade tree looks something like:
 | 
        
           |  |  | 89 |         // - Test course n        (Rendered).
 | 
        
           |  |  | 90 |         // -- Grade category n    (Rendered).
 | 
        
           |  |  | 91 |         // -- No total category   (Not rendered).
 | 
        
           |  |  | 92 |         $gradetree = \grade_category::fetch_course_tree($course->id);
 | 
        
           |  |  | 93 |         foreach ($gradetree['children'] as $child) {
 | 
        
           |  |  | 94 |             if ($child['object']->fullname == $nototalcategory) {
 | 
        
           |  |  | 95 |                 $this->assertFalse(\grade_tree::can_output_item($child));
 | 
        
           |  |  | 96 |             } else {
 | 
        
           |  |  | 97 |                 $this->assertTrue(\grade_tree::can_output_item($child));
 | 
        
           |  |  | 98 |             }
 | 
        
           |  |  | 99 |         }
 | 
        
           |  |  | 100 |   | 
        
           |  |  | 101 |         // Add another grade category with default settings under 'No total category'.
 | 
        
           |  |  | 102 |         $normalinnototalparams = [
 | 
        
           |  |  | 103 |             'courseid' => $course->id,
 | 
        
           |  |  | 104 |             'fullname' => 'Normal category in no total category',
 | 
        
           |  |  | 105 |             'parent' => $nototal->id
 | 
        
           |  |  | 106 |         ];
 | 
        
           |  |  | 107 |         $generator->create_grade_category($normalinnototalparams);
 | 
        
           |  |  | 108 |   | 
        
           |  |  | 109 |         // Grade tree looks something like:
 | 
        
           |  |  | 110 |         // - Test course n                           (Rendered).
 | 
        
           |  |  | 111 |         // -- Grade category n                       (Rendered).
 | 
        
           |  |  | 112 |         // -- No total category                      (Rendered).
 | 
        
           |  |  | 113 |         // --- Normal category in no total category  (Rendered).
 | 
        
           |  |  | 114 |         $gradetree = \grade_category::fetch_course_tree($course->id);
 | 
        
           |  |  | 115 |         foreach ($gradetree['children'] as $child) {
 | 
        
           |  |  | 116 |             // All children are now visible.
 | 
        
           |  |  | 117 |             $this->assertTrue(\grade_tree::can_output_item($child));
 | 
        
           |  |  | 118 |             if (!empty($child['children'])) {
 | 
        
           |  |  | 119 |                 foreach ($child['children'] as $grandchild) {
 | 
        
           |  |  | 120 |                     $this->assertTrue(\grade_tree::can_output_item($grandchild));
 | 
        
           |  |  | 121 |                 }
 | 
        
           |  |  | 122 |             }
 | 
        
           |  |  | 123 |         }
 | 
        
           |  |  | 124 |   | 
        
           |  |  | 125 |         // Add a grade category with grade type = None.
 | 
        
           |  |  | 126 |         $nototalcategory2 = 'No total category 2';
 | 
        
           |  |  | 127 |         $nototal2params = [
 | 
        
           |  |  | 128 |             'courseid' => $course->id,
 | 
        
           |  |  | 129 |             'fullname' => $nototalcategory2,
 | 
        
           |  |  | 130 |             'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN
 | 
        
           |  |  | 131 |         ];
 | 
        
           |  |  | 132 |         $nototal2 = $generator->create_grade_category($nototal2params);
 | 
        
           |  |  | 133 |         $catnototal2 = \grade_category::fetch(array('id' => $nototal2->id));
 | 
        
           |  |  | 134 |         // Set the grade type of the grade item associated to the grade category.
 | 
        
           |  |  | 135 |         $catitemnototal2 = $catnototal2->load_grade_item();
 | 
        
           |  |  | 136 |         $catitemnototal2->gradetype = GRADE_TYPE_NONE;
 | 
        
           |  |  | 137 |         $catitemnototal2->update();
 | 
        
           |  |  | 138 |   | 
        
           |  |  | 139 |         // Add a category with no total under 'No total category'.
 | 
        
           |  |  | 140 |         $nototalinnototalcategory = 'Category with no total in no total category';
 | 
        
           |  |  | 141 |         $nototalinnototalparams = [
 | 
        
           |  |  | 142 |             'courseid' => $course->id,
 | 
        
           |  |  | 143 |             'fullname' => $nototalinnototalcategory,
 | 
        
           |  |  | 144 |             'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN,
 | 
        
           |  |  | 145 |             'parent' => $nototal2->id
 | 
        
           |  |  | 146 |         ];
 | 
        
           |  |  | 147 |         $nototalinnototal = $generator->create_grade_category($nototalinnototalparams);
 | 
        
           |  |  | 148 |         $catnototalinnototal = \grade_category::fetch(array('id' => $nototalinnototal->id));
 | 
        
           |  |  | 149 |         // Set the grade type of the grade item associated to the grade category.
 | 
        
           |  |  | 150 |         $catitemnototalinnototal = $catnototalinnototal->load_grade_item();
 | 
        
           |  |  | 151 |         $catitemnototalinnototal->gradetype = GRADE_TYPE_NONE;
 | 
        
           |  |  | 152 |         $catitemnototalinnototal->update();
 | 
        
           |  |  | 153 |   | 
        
           |  |  | 154 |         // Grade tree looks something like:
 | 
        
           |  |  | 155 |         // - Test course n                                    (Rendered).
 | 
        
           |  |  | 156 |         // -- Grade category n                                (Rendered).
 | 
        
           |  |  | 157 |         // -- No total category                               (Rendered).
 | 
        
           |  |  | 158 |         // --- Normal category in no total category           (Rendered).
 | 
        
           |  |  | 159 |         // -- No total category 2                             (Not rendered).
 | 
        
           |  |  | 160 |         // --- Category with no total in no total category    (Not rendered).
 | 
        
           |  |  | 161 |         $gradetree = \grade_category::fetch_course_tree($course->id);
 | 
        
           |  |  | 162 |         foreach ($gradetree['children'] as $child) {
 | 
        
           |  |  | 163 |             if ($child['object']->fullname == $nototalcategory2) {
 | 
        
           |  |  | 164 |                 $this->assertFalse(\grade_tree::can_output_item($child));
 | 
        
           |  |  | 165 |             } else {
 | 
        
           |  |  | 166 |                 $this->assertTrue(\grade_tree::can_output_item($child));
 | 
        
           |  |  | 167 |             }
 | 
        
           |  |  | 168 |             if (!empty($child['children'])) {
 | 
        
           |  |  | 169 |                 foreach ($child['children'] as $grandchild) {
 | 
        
           |  |  | 170 |                     if ($grandchild['object']->fullname == $nototalinnototalcategory) {
 | 
        
           |  |  | 171 |                         $this->assertFalse(\grade_tree::can_output_item($grandchild));
 | 
        
           |  |  | 172 |                     } else {
 | 
        
           |  |  | 173 |                         $this->assertTrue(\grade_tree::can_output_item($grandchild));
 | 
        
           |  |  | 174 |                     }
 | 
        
           |  |  | 175 |                 }
 | 
        
           |  |  | 176 |             }
 | 
        
           |  |  | 177 |         }
 | 
        
           |  |  | 178 |     }
 | 
        
           |  |  | 179 |   | 
        
           |  |  | 180 |     /**
 | 
        
           |  |  | 181 |      * Tests that ungraded_counts calculates count and sum of grades correctly when there are graded users.
 | 
        
           |  |  | 182 |      *
 | 
        
           |  |  | 183 |      * @covers \grade_report::ungraded_counts
 | 
        
           |  |  | 184 |      */
 | 
        
           | 11 | efrain | 185 |     public function test_ungraded_counts_count_sumgrades(): void {
 | 
        
           | 1 | efrain | 186 |         global $DB;
 | 
        
           |  |  | 187 |   | 
        
           |  |  | 188 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 189 |   | 
        
           |  |  | 190 |         $course1 = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 191 |         $course2 = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 |         $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
 | 
        
           |  |  | 194 |         $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher'], '*', MUST_EXIST);
 | 
        
           |  |  | 195 |   | 
        
           |  |  | 196 |         // Custom roles (gradable and non gradable).
 | 
        
           |  |  | 197 |         $gradeblerole = create_role('New student role', 'gradable',
 | 
        
           |  |  | 198 |             'Gradable role', 'student');
 | 
        
           |  |  | 199 |         $nongradeblerole = create_role('New student role', 'nongradable',
 | 
        
           |  |  | 200 |             'Non gradable role', 'student');
 | 
        
           |  |  | 201 |   | 
        
           |  |  | 202 |         // Set up gradable roles.
 | 
        
           |  |  | 203 |         set_config('gradebookroles', $studentrole->id . ',' . $gradeblerole);
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 |         // Create users.
 | 
        
           |  |  | 206 |   | 
        
           |  |  | 207 |         // These will be gradable users.
 | 
        
           |  |  | 208 |         $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']);
 | 
        
           |  |  | 209 |         $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']);
 | 
        
           |  |  | 210 |         $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']);
 | 
        
           |  |  | 211 |         $student5 = $this->getDataGenerator()->create_user(['username' => 'student5']);
 | 
        
           |  |  | 212 |   | 
        
           |  |  | 213 |         // These will be non-gradable users.
 | 
        
           |  |  | 214 |         $student4 = $this->getDataGenerator()->create_user(['username' => 'student4']);
 | 
        
           |  |  | 215 |         $student6 = $this->getDataGenerator()->create_user(['username' => 'student6']);
 | 
        
           |  |  | 216 |         $teacher = $this->getDataGenerator()->create_user(['username' => 'teacher']);
 | 
        
           |  |  | 217 |   | 
        
           |  |  | 218 |         // Enrol students.
 | 
        
           |  |  | 219 |         $this->getDataGenerator()->enrol_user($student1->id, $course1->id, $studentrole->id);
 | 
        
           |  |  | 220 |         $this->getDataGenerator()->enrol_user($student2->id, $course1->id, $studentrole->id);
 | 
        
           |  |  | 221 |         $this->getDataGenerator()->enrol_user($student3->id, $course1->id, $gradeblerole);
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |         $this->getDataGenerator()->enrol_user($student5->id, $course1->id, $nongradeblerole);
 | 
        
           |  |  | 224 |         $this->getDataGenerator()->enrol_user($student6->id, $course1->id, $studentrole->id);
 | 
        
           |  |  | 225 |         $this->getDataGenerator()->enrol_user($teacher->id, $course1->id, $teacherrole->id);
 | 
        
           |  |  | 226 |   | 
        
           |  |  | 227 |         // User that is enrolled in a different course.
 | 
        
           |  |  | 228 |         $this->getDataGenerator()->enrol_user($student4->id, $course2->id, $studentrole->id);
 | 
        
           |  |  | 229 |   | 
        
           |  |  | 230 |         // Mark user as deleted.
 | 
        
           |  |  | 231 |         $student6->deleted = 1;
 | 
        
           |  |  | 232 |         $DB->update_record('user', $student6);
 | 
        
           |  |  | 233 |   | 
        
           |  |  | 234 |         // Create grade items in course 1.
 | 
        
           |  |  | 235 |         $assign1 = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]);
 | 
        
           |  |  | 236 |         $assign2 = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]);
 | 
        
           |  |  | 237 |         $quiz1 = $this->getDataGenerator()->create_module('quiz', ['course' => $course1->id]);
 | 
        
           |  |  | 238 |   | 
        
           |  |  | 239 |         $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([
 | 
        
           |  |  | 240 |             'itemname'        => 'Grade item1',
 | 
        
           |  |  | 241 |             'idnumber'        => 'git1',
 | 
        
           |  |  | 242 |             'courseid'        => $course1->id,
 | 
        
           |  |  | 243 |         ]));
 | 
        
           |  |  | 244 |   | 
        
           |  |  | 245 |         // Create grade items in course 2.
 | 
        
           |  |  | 246 |         $assign3 = $this->getDataGenerator()->create_module('assign', ['course' => $course2->id]);
 | 
        
           |  |  | 247 |   | 
        
           |  |  | 248 |         // Grade users in first course.
 | 
        
           |  |  | 249 |         $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign1->id));
 | 
        
           |  |  | 250 |         $assigninstance = new assign($cm->context, $cm, $course1);
 | 
        
           |  |  | 251 |         $grade = $assigninstance->get_user_grade($student1->id, true);
 | 
        
           |  |  | 252 |         $grade->grade = 40;
 | 
        
           |  |  | 253 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 254 |   | 
        
           |  |  | 255 |         $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign2->id));
 | 
        
           |  |  | 256 |         $assigninstance = new assign($cm->context, $cm, $course1);
 | 
        
           |  |  | 257 |         $grade = $assigninstance->get_user_grade($student3->id, true);
 | 
        
           |  |  | 258 |         $grade->grade = 50;
 | 
        
           |  |  | 259 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 260 |   | 
        
           |  |  | 261 |         // Override grade for assignment in gradebook.
 | 
        
           |  |  | 262 |         $gi = \grade_item::fetch([
 | 
        
           |  |  | 263 |             'itemtype' => 'mod',
 | 
        
           |  |  | 264 |             'itemmodule' => 'assign',
 | 
        
           |  |  | 265 |             'iteminstance' => $cm->instance,
 | 
        
           |  |  | 266 |             'courseid' => $course1->id
 | 
        
           |  |  | 267 |         ]);
 | 
        
           |  |  | 268 |         $gi->update_final_grade($student3->id, 55);
 | 
        
           |  |  | 269 |   | 
        
           |  |  | 270 |         // Grade user in second course.
 | 
        
           |  |  | 271 |         $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign3->id));
 | 
        
           |  |  | 272 |         $assigninstance = new assign($cm->context, $cm, $course2);
 | 
        
           |  |  | 273 |         $grade = $assigninstance->get_user_grade($student4->id, true);
 | 
        
           |  |  | 274 |         $grade->grade = 40;
 | 
        
           |  |  | 275 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 276 |   | 
        
           |  |  | 277 |         $manuaitem->update_final_grade($student1->id, 1);
 | 
        
           |  |  | 278 |         $manuaitem->update_final_grade($student3->id, 2);
 | 
        
           |  |  | 279 |   | 
        
           |  |  | 280 |         // Trigger a regrade.
 | 
        
           |  |  | 281 |         grade_force_full_regrading($course1->id);
 | 
        
           |  |  | 282 |         grade_force_full_regrading($course2->id);
 | 
        
           |  |  | 283 |         grade_regrade_final_grades($course1->id);
 | 
        
           |  |  | 284 |         grade_regrade_final_grades($course2->id);
 | 
        
           |  |  | 285 |   | 
        
           |  |  | 286 |         // Initialise reports.
 | 
        
           |  |  | 287 |         $context1 = \context_course::instance($course1->id);
 | 
        
           |  |  | 288 |         $context2 = \context_course::instance($course2->id);
 | 
        
           |  |  | 289 |   | 
        
           |  |  | 290 |         $gpr1 = new grade_plugin_return(
 | 
        
           |  |  | 291 |             [
 | 
        
           |  |  | 292 |                 'type' => 'report',
 | 
        
           |  |  | 293 |                 'plugin' => 'grader',
 | 
        
           |  |  | 294 |                 'course' => $course1,
 | 
        
           |  |  | 295 |             ]
 | 
        
           |  |  | 296 |         );
 | 
        
           |  |  | 297 |   | 
        
           |  |  | 298 |         $gpr2 = new grade_plugin_return(
 | 
        
           |  |  | 299 |             [
 | 
        
           |  |  | 300 |                 'type' => 'report',
 | 
        
           |  |  | 301 |                 'plugin' => 'grader',
 | 
        
           |  |  | 302 |                 'course' => $course2,
 | 
        
           |  |  | 303 |             ]
 | 
        
           |  |  | 304 |         );
 | 
        
           |  |  | 305 |   | 
        
           |  |  | 306 |         $report1 = new grade_report_grader($course1->id, $gpr1, $context1);
 | 
        
           |  |  | 307 |         $report2 = new grade_report_grader($course2->id, $gpr2, $context2);
 | 
        
           |  |  | 308 |   | 
        
           |  |  | 309 |         $ungradedcounts = [];
 | 
        
           |  |  | 310 |         $ungradedcounts[$course1->id] = $report1->ungraded_counts(false);
 | 
        
           |  |  | 311 |         $ungradedcounts[$course2->id] = $report2->ungraded_counts(false);
 | 
        
           |  |  | 312 |   | 
        
           |  |  | 313 |         foreach ($ungradedcounts as $key => $ungradedcount) {
 | 
        
           |  |  | 314 |             $gradeitems = grade_item::fetch_all(['courseid' => $key]);
 | 
        
           |  |  | 315 |             if ($key == $course1->id) {
 | 
        
           |  |  | 316 |                 $gradeitemkeys = array_keys($gradeitems);
 | 
        
           |  |  | 317 |                 $ungradedcountskeys = array_keys($ungradedcount['ungradedcounts']);
 | 
        
           |  |  | 318 |   | 
        
           |  |  | 319 |                 // For each grade item there is some student that is not graded yet in course 1.
 | 
        
           |  |  | 320 |                 $this->assertEmpty(array_diff_key($gradeitemkeys, $ungradedcountskeys));
 | 
        
           |  |  | 321 |   | 
        
           |  |  | 322 |                 // Only quiz does not have any grades, the remaning 4 grade items should have some.
 | 
        
           |  |  | 323 |                 // We can do more and match by gradeitem id numbers. But feels like overengeneering.
 | 
        
           |  |  | 324 |                 $this->assertEquals(4, count($ungradedcount['sumarray']));
 | 
        
           |  |  | 325 |             } else {
 | 
        
           |  |  | 326 |   | 
        
           |  |  | 327 |                 // In course 2 there is one student, and he is graded.
 | 
        
           |  |  | 328 |                 $this->assertEmpty($ungradedcount['ungradedcounts']);
 | 
        
           |  |  | 329 |   | 
        
           |  |  | 330 |                 // There are 2 grade items and they both have some grades.
 | 
        
           |  |  | 331 |                 $this->assertEquals(2, count($ungradedcount['sumarray']));
 | 
        
           |  |  | 332 |             }
 | 
        
           |  |  | 333 |   | 
        
           |  |  | 334 |             foreach ($gradeitems as $gradeitem) {
 | 
        
           |  |  | 335 |                 $sumgrades = null;
 | 
        
           |  |  | 336 |                 if (array_key_exists($gradeitem->id, $ungradedcount['ungradedcounts'])) {
 | 
        
           |  |  | 337 |                     $ungradeditem = $ungradedcount['ungradedcounts'][$gradeitem->id];
 | 
        
           |  |  | 338 |                     if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 339 |                         $this->assertEquals(1, $ungradeditem->count);
 | 
        
           |  |  | 340 |                     } else if ($gradeitem->itemmodule === 'assign') {
 | 
        
           |  |  | 341 |                         $this->assertEquals(2, $ungradeditem->count);
 | 
        
           |  |  | 342 |                     } else if ($gradeitem->itemmodule === 'quiz') {
 | 
        
           |  |  | 343 |                         $this->assertEquals(3, $ungradeditem->count);
 | 
        
           |  |  | 344 |                     } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 345 |                         $this->assertEquals(1, $ungradeditem->count);
 | 
        
           |  |  | 346 |                     }
 | 
        
           |  |  | 347 |                 }
 | 
        
           |  |  | 348 |   | 
        
           |  |  | 349 |                 if (array_key_exists($gradeitem->id, $ungradedcount['sumarray'])) {
 | 
        
           |  |  | 350 |                     $sumgrades = $ungradedcount['sumarray'][$gradeitem->id];
 | 
        
           |  |  | 351 |                     if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 352 |                         if ($key == $course1->id) {
 | 
        
           |  |  | 353 |                             $this->assertEquals('98.00000', $sumgrades); // 40 + 55 + 1 + 2
 | 
        
           |  |  | 354 |                         } else {
 | 
        
           |  |  | 355 |                             $this->assertEquals('40.00000', $sumgrades);
 | 
        
           |  |  | 356 |                         }
 | 
        
           |  |  | 357 |                     } else if ($gradeitem->itemmodule === 'assign') {
 | 
        
           |  |  | 358 |                         if (($gradeitem->itemname === $assign1->name) || ($gradeitem->itemname === $assign3->name)) {
 | 
        
           |  |  | 359 |                             $this->assertEquals('40.00000', $sumgrades);
 | 
        
           |  |  | 360 |                         } else {
 | 
        
           |  |  | 361 |                             $this->assertEquals('55.00000', $sumgrades);
 | 
        
           |  |  | 362 |                         }
 | 
        
           |  |  | 363 |                     } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 364 |                         $this->assertEquals('3.00000', $sumgrades);
 | 
        
           |  |  | 365 |                     }
 | 
        
           |  |  | 366 |                 }
 | 
        
           |  |  | 367 |             }
 | 
        
           |  |  | 368 |         }
 | 
        
           |  |  | 369 |     }
 | 
        
           |  |  | 370 |   | 
        
           |  |  | 371 |     /**
 | 
        
           |  |  | 372 |      * Tests that ungraded_counts calculates count and sum of grades correctly when there are hidden grades.
 | 
        
           |  |  | 373 |      * @dataProvider ungraded_counts_hidden_grades_data()
 | 
        
           |  |  | 374 |      * @param bool $hidden Whether to inlcude hidden grades or not.
 | 
        
           |  |  | 375 |      * @param array $expectedcount expected count value (i.e. number of ugraded grades)
 | 
        
           |  |  | 376 |      * @param array $expectedsumarray expceted sum of grades
 | 
        
           |  |  | 377 |      *
 | 
        
           |  |  | 378 |      * @covers \grade_report::ungraded_counts
 | 
        
           |  |  | 379 |      */
 | 
        
           | 11 | efrain | 380 |     public function test_ungraded_counts_hidden_grades(bool $hidden, array $expectedcount, array $expectedsumarray): void {
 | 
        
           | 1 | efrain | 381 |         $this->resetAfterTest();
 | 
        
           |  |  | 382 |   | 
        
           |  |  | 383 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 384 |   | 
        
           |  |  | 385 |         // Create users.
 | 
        
           |  |  | 386 |         $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']);
 | 
        
           |  |  | 387 |         $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']);
 | 
        
           |  |  | 388 |         $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']);
 | 
        
           |  |  | 389 |   | 
        
           |  |  | 390 |         // Enrol students.
 | 
        
           |  |  | 391 |         $this->getDataGenerator()->enrol_user($student1->id, $course->id, 'student');
 | 
        
           |  |  | 392 |         $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student');
 | 
        
           |  |  | 393 |         $this->getDataGenerator()->enrol_user($student3->id, $course->id, 'student');
 | 
        
           |  |  | 394 |   | 
        
           |  |  | 395 |         // Create grade items in course.
 | 
        
           |  |  | 396 |         $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([
 | 
        
           |  |  | 397 |             'itemname' => 'Grade item1',
 | 
        
           |  |  | 398 |             'idnumber' => 'git1',
 | 
        
           |  |  | 399 |             'courseid' => $course->id,
 | 
        
           |  |  | 400 |         ]));
 | 
        
           |  |  | 401 |   | 
        
           |  |  | 402 |         // Grade users.
 | 
        
           |  |  | 403 |         $manuaitem->update_final_grade($student1->id, 1);
 | 
        
           |  |  | 404 |         $manuaitem->update_final_grade($student3->id, 2);
 | 
        
           |  |  | 405 |   | 
        
           |  |  | 406 |         // Create a hidden grade.
 | 
        
           |  |  | 407 |         $manuaitem->update_final_grade($student2->id, 3);
 | 
        
           |  |  | 408 |         $grade = \grade_grade::fetch(['itemid' => $manuaitem->id, 'userid' => $student2->id]);
 | 
        
           |  |  | 409 |         $grade->hidden = 1;
 | 
        
           |  |  | 410 |         $grade->update();
 | 
        
           |  |  | 411 |   | 
        
           |  |  | 412 |         // Trigger a regrade.
 | 
        
           |  |  | 413 |         grade_force_full_regrading($course->id);
 | 
        
           |  |  | 414 |         grade_regrade_final_grades($course->id);
 | 
        
           |  |  | 415 |   | 
        
           |  |  | 416 |         // Initialise reports.
 | 
        
           |  |  | 417 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 418 |   | 
        
           |  |  | 419 |         $gpr = new grade_plugin_return(
 | 
        
           |  |  | 420 |             [
 | 
        
           |  |  | 421 |                 'type' => 'report',
 | 
        
           |  |  | 422 |                 'plugin' => 'grader',
 | 
        
           |  |  | 423 |                 'course' => $course,
 | 
        
           |  |  | 424 |             ]
 | 
        
           |  |  | 425 |         );
 | 
        
           |  |  | 426 |   | 
        
           |  |  | 427 |         $report = new grade_report_grader($course->id, $gpr, $context);
 | 
        
           |  |  | 428 |   | 
        
           |  |  | 429 |         $ungradedcounts = $report->ungraded_counts(false, $hidden);
 | 
        
           |  |  | 430 |   | 
        
           |  |  | 431 |         $gradeitems = grade_item::fetch_all(['courseid' => $course->id]);
 | 
        
           |  |  | 432 |   | 
        
           |  |  | 433 |         foreach ($gradeitems as $gradeitem) {
 | 
        
           |  |  | 434 |             $sumgrades = null;
 | 
        
           |  |  | 435 |             if (array_key_exists($gradeitem->id, $ungradedcounts['ungradedcounts'])) {
 | 
        
           |  |  | 436 |                 $ungradeditem = $ungradedcounts['ungradedcounts'][$gradeitem->id];
 | 
        
           |  |  | 437 |                 if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 438 |                     $this->assertEquals($expectedcount['course'], $ungradeditem->count);
 | 
        
           |  |  | 439 |                 } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 440 |                     $this->assertEquals($expectedcount['Grade item1'], $ungradeditem->count);
 | 
        
           |  |  | 441 |                 }
 | 
        
           |  |  | 442 |             }
 | 
        
           |  |  | 443 |   | 
        
           |  |  | 444 |             if (array_key_exists($gradeitem->id, $ungradedcounts['sumarray'])) {
 | 
        
           |  |  | 445 |                 $sumgrades = $ungradedcounts['sumarray'][$gradeitem->id];
 | 
        
           |  |  | 446 |                 if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 447 |                     $this->assertEquals($expectedsumarray['course'], $sumgrades);
 | 
        
           |  |  | 448 |                 } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 449 |                     $this->assertEquals($expectedsumarray['Grade item1'], $sumgrades);
 | 
        
           |  |  | 450 |                 }
 | 
        
           |  |  | 451 |             }
 | 
        
           |  |  | 452 |         }
 | 
        
           |  |  | 453 |     }
 | 
        
           |  |  | 454 |   | 
        
           |  |  | 455 |     /**
 | 
        
           |  |  | 456 |      * Data provider for test_ungraded_counts_hidden_grades
 | 
        
           |  |  | 457 |      *
 | 
        
           |  |  | 458 |      * @return array of testing scenarios
 | 
        
           |  |  | 459 |      */
 | 
        
           |  |  | 460 |     public function ungraded_counts_hidden_grades_data(): array {
 | 
        
           |  |  | 461 |         return [
 | 
        
           |  |  | 462 |             'nohidden' => [
 | 
        
           |  |  | 463 |                 'hidden' => false,
 | 
        
           |  |  | 464 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 465 |                 'sumarray' => ['course' => 6.00000, 'Grade item1' => 3.00000],
 | 
        
           |  |  | 466 |             ],
 | 
        
           |  |  | 467 |             'includehidden' => [
 | 
        
           |  |  | 468 |                 'hidden' => true,
 | 
        
           |  |  | 469 |                 'count' => ['course' => 1, 'Grade item1' => 2],
 | 
        
           |  |  | 470 |                 'sumarray' => ['course' => 6.00000, 'Grade item1' => 6.00000],
 | 
        
           |  |  | 471 |             ],
 | 
        
           |  |  | 472 |         ];
 | 
        
           |  |  | 473 |     }
 | 
        
           |  |  | 474 |   | 
        
           |  |  | 475 |     /**
 | 
        
           |  |  | 476 |      * Tests that ungraded_counts calculates count and sum of grades correctly for groups when there are graded users.
 | 
        
           |  |  | 477 |      *
 | 
        
           |  |  | 478 |      * @covers \grade_report::ungraded_counts
 | 
        
           |  |  | 479 |      */
 | 
        
           | 11 | efrain | 480 |     public function test_ungraded_count_sumgrades_groups(): void {
 | 
        
           | 1 | efrain | 481 |         global $DB;
 | 
        
           |  |  | 482 |   | 
        
           |  |  | 483 |         $this->resetAfterTest();
 | 
        
           |  |  | 484 |   | 
        
           |  |  | 485 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 486 |   | 
        
           |  |  | 487 |         $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
 | 
        
           |  |  | 488 |   | 
        
           |  |  | 489 |         // Create users.
 | 
        
           |  |  | 490 |         $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']);
 | 
        
           |  |  | 491 |         $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']);
 | 
        
           |  |  | 492 |         $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']);
 | 
        
           |  |  | 493 |   | 
        
           |  |  | 494 |         // Enrol students.
 | 
        
           |  |  | 495 |         $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
 | 
        
           |  |  | 496 |         $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
 | 
        
           |  |  | 497 |         $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id);
 | 
        
           |  |  | 498 |   | 
        
           |  |  | 499 |         $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 | 
        
           |  |  | 500 |         $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 | 
        
           |  |  | 501 |         $this->getDataGenerator()->create_group_member(['userid' => $student1->id, 'groupid' => $group1->id]);
 | 
        
           |  |  | 502 |         $this->getDataGenerator()->create_group_member(['userid' => $student2->id, 'groupid' => $group2->id]);
 | 
        
           |  |  | 503 |         $this->getDataGenerator()->create_group_member(['userid' => $student3->id, 'groupid' => $group2->id]);
 | 
        
           |  |  | 504 |         $DB->set_field('course', 'groupmode', SEPARATEGROUPS, ['id' => $course->id]);
 | 
        
           |  |  | 505 |   | 
        
           |  |  | 506 |         // Create grade items.
 | 
        
           |  |  | 507 |         $assign1 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]);
 | 
        
           |  |  | 508 |         $assign2 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]);
 | 
        
           |  |  | 509 |         $quiz1 = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
 | 
        
           |  |  | 510 |   | 
        
           |  |  | 511 |         $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([
 | 
        
           |  |  | 512 |             'itemname'        => 'Grade item1',
 | 
        
           |  |  | 513 |             'idnumber'        => 'git1',
 | 
        
           |  |  | 514 |             'courseid'        => $course->id,
 | 
        
           |  |  | 515 |         ]));
 | 
        
           |  |  | 516 |   | 
        
           |  |  | 517 |         // Grade users.
 | 
        
           |  |  | 518 |         $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign1->id));
 | 
        
           |  |  | 519 |         $assigninstance = new assign($cm->context, $cm, $course);
 | 
        
           |  |  | 520 |         $grade = $assigninstance->get_user_grade($student1->id, true);
 | 
        
           |  |  | 521 |         $grade->grade = 40;
 | 
        
           |  |  | 522 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 523 |   | 
        
           |  |  | 524 |         $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign2->id));
 | 
        
           |  |  | 525 |         $assigninstance = new assign($cm->context, $cm, $course);
 | 
        
           |  |  | 526 |         $grade = $assigninstance->get_user_grade($student3->id, true);
 | 
        
           |  |  | 527 |         $grade->grade = 50;
 | 
        
           |  |  | 528 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 529 |   | 
        
           |  |  | 530 |         $manuaitem->update_final_grade($student1->id, 1);
 | 
        
           |  |  | 531 |         $manuaitem->update_final_grade($student3->id, 2);
 | 
        
           |  |  | 532 |   | 
        
           |  |  | 533 |         // Trigger a regrade.
 | 
        
           |  |  | 534 |         grade_force_full_regrading($course->id);
 | 
        
           |  |  | 535 |         grade_regrade_final_grades($course->id);
 | 
        
           |  |  | 536 |   | 
        
           |  |  | 537 |         // Initialise report.
 | 
        
           |  |  | 538 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 539 |   | 
        
           |  |  | 540 |         $gpr1 = new grade_plugin_return(
 | 
        
           |  |  | 541 |             [
 | 
        
           |  |  | 542 |                 'type' => 'report',
 | 
        
           |  |  | 543 |                 'plugin' => 'grader',
 | 
        
           |  |  | 544 |                 'course' => $course,
 | 
        
           |  |  | 545 |                 'groupid' => $group1->id,
 | 
        
           |  |  | 546 |             ]
 | 
        
           |  |  | 547 |         );
 | 
        
           |  |  | 548 |   | 
        
           |  |  | 549 |         $gpr2 = new grade_plugin_return(
 | 
        
           |  |  | 550 |             [
 | 
        
           |  |  | 551 |                 'type' => 'report',
 | 
        
           |  |  | 552 |                 'plugin' => 'grader',
 | 
        
           |  |  | 553 |                 'course' => $course,
 | 
        
           |  |  | 554 |                 'groupid' => $group2->id,
 | 
        
           |  |  | 555 |             ]
 | 
        
           |  |  | 556 |         );
 | 
        
           |  |  | 557 |   | 
        
           |  |  | 558 |         $report1 = new grade_report_grader($course->id, $gpr1, $context);
 | 
        
           |  |  | 559 |         $report2 = new grade_report_grader($course->id, $gpr2, $context);
 | 
        
           |  |  | 560 |   | 
        
           |  |  | 561 |         $ungradedcounts = [];
 | 
        
           |  |  | 562 |         $ungradedcounts[$group1->id] = $report1->ungraded_counts(true);
 | 
        
           |  |  | 563 |         $ungradedcounts[$group2->id] = $report2->ungraded_counts(true);
 | 
        
           |  |  | 564 |   | 
        
           |  |  | 565 |         $gradeitems = grade_item::fetch_all(['courseid' => $course->id]);
 | 
        
           |  |  | 566 |   | 
        
           |  |  | 567 |         // In group1 there is 1 student and assign1 and quiz1 are not graded for him.
 | 
        
           |  |  | 568 |         $this->assertEquals(2, count($ungradedcounts[$group1->id]['ungradedcounts']));
 | 
        
           |  |  | 569 |   | 
        
           |  |  | 570 |         // In group1 manual grade item, assign1 and course total have some grades.
 | 
        
           |  |  | 571 |         $this->assertEquals(3, count($ungradedcounts[$group1->id]['sumarray']));
 | 
        
           |  |  | 572 |   | 
        
           |  |  | 573 |         // In group2 student2 has no grades at all so all 5 grade items should present.
 | 
        
           |  |  | 574 |         $this->assertEquals(5, count($ungradedcounts[$group2->id]['ungradedcounts']));
 | 
        
           |  |  | 575 |   | 
        
           |  |  | 576 |         // In group2 manual grade item, assign2 and course total have some grades.
 | 
        
           |  |  | 577 |         $this->assertEquals(3, count($ungradedcounts[$group2->id]['sumarray']));
 | 
        
           |  |  | 578 |   | 
        
           |  |  | 579 |         foreach ($gradeitems as $gradeitem) {
 | 
        
           |  |  | 580 |             $sumgrades = null;
 | 
        
           |  |  | 581 |   | 
        
           |  |  | 582 |             foreach ($ungradedcounts as $key => $ungradedcount) {
 | 
        
           |  |  | 583 |                 if (array_key_exists($gradeitem->id, $ungradedcount['ungradedcounts'])) {
 | 
        
           |  |  | 584 |                     $ungradeditem = $ungradedcount['ungradedcounts'][$gradeitem->id];
 | 
        
           |  |  | 585 |                     if ($key == $group1->id) {
 | 
        
           |  |  | 586 |                         // Both assign2 and quiz1 are not graded for student1.
 | 
        
           |  |  | 587 |                         $this->assertEquals(1, $ungradeditem->count);
 | 
        
           |  |  | 588 |                     } else {
 | 
        
           |  |  | 589 |                         if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 590 |                             $this->assertEquals(1, $ungradeditem->count);
 | 
        
           |  |  | 591 |                         } else if ($gradeitem->itemmodule === 'assign') {
 | 
        
           |  |  | 592 |                             if ($gradeitem->itemname === $assign1->name) {
 | 
        
           |  |  | 593 |                                 // In group2 assign1 is not graded for anyone.
 | 
        
           |  |  | 594 |                                 $this->assertEquals(2, $ungradeditem->count);
 | 
        
           |  |  | 595 |                             } else {
 | 
        
           |  |  | 596 |                                 // In group2 assign2 is graded for student3.
 | 
        
           |  |  | 597 |                                 $this->assertEquals(1, $ungradeditem->count);
 | 
        
           |  |  | 598 |                             }
 | 
        
           |  |  | 599 |                         } else if ($gradeitem->itemmodule === 'quiz') {
 | 
        
           |  |  | 600 |                             $this->assertEquals(2, $ungradeditem->count);
 | 
        
           |  |  | 601 |                         } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 602 |                             $this->assertEquals(1, $ungradeditem->count);
 | 
        
           |  |  | 603 |                         }
 | 
        
           |  |  | 604 |                     }
 | 
        
           |  |  | 605 |                 }
 | 
        
           |  |  | 606 |   | 
        
           |  |  | 607 |                 if (array_key_exists($gradeitem->id, $ungradedcount['sumarray'])) {
 | 
        
           |  |  | 608 |                     $sumgrades = $ungradedcount['sumarray'][$gradeitem->id];
 | 
        
           |  |  | 609 |                     if ($key == $group1->id) {
 | 
        
           |  |  | 610 |                         if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 611 |                             $this->assertEquals('41.00000', $sumgrades);
 | 
        
           |  |  | 612 |                         } else if ($gradeitem->itemmodule === 'assign') {
 | 
        
           |  |  | 613 |                             $this->assertEquals('40.00000', $sumgrades);
 | 
        
           |  |  | 614 |                         } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 615 |                             $this->assertEquals('1.00000', $sumgrades);
 | 
        
           |  |  | 616 |                         }
 | 
        
           |  |  | 617 |                     } else {
 | 
        
           |  |  | 618 |                         if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 619 |                             $this->assertEquals('52.00000', $sumgrades);
 | 
        
           |  |  | 620 |                         } else if ($gradeitem->itemmodule === 'assign') {
 | 
        
           |  |  | 621 |                             $this->assertEquals('50.00000', $sumgrades);
 | 
        
           |  |  | 622 |                         } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 623 |                             $this->assertEquals('2.00000', $sumgrades);
 | 
        
           |  |  | 624 |                         }
 | 
        
           |  |  | 625 |                     }
 | 
        
           |  |  | 626 |                 }
 | 
        
           |  |  | 627 |             }
 | 
        
           |  |  | 628 |         }
 | 
        
           |  |  | 629 |     }
 | 
        
           |  |  | 630 |   | 
        
           |  |  | 631 |     /**
 | 
        
           |  |  | 632 |      * Tests that ungraded_counts calculates count and sum of grades correctly when there are hidden grades.
 | 
        
           |  |  | 633 |      * @dataProvider ungraded_counts_only_active_enrol_data()
 | 
        
           |  |  | 634 |      * @param bool $onlyactive Site setting to show only active users.
 | 
        
           |  |  | 635 |      * @param int $hascapability Capability constant
 | 
        
           |  |  | 636 |      * @param bool|null $showonlyactiveenrolpref Show only active user preference.
 | 
        
           |  |  | 637 |      * @param array $expectedcount expected count value (i.e. number of ugraded grades)
 | 
        
           |  |  | 638 |      * @param array $expectedsumarray expected sum of grades
 | 
        
           |  |  | 639 |      *
 | 
        
           |  |  | 640 |      * @covers \grade_report::ungraded_counts
 | 
        
           |  |  | 641 |      */
 | 
        
           |  |  | 642 |     public function test_ungraded_counts_only_active_enrol(bool $onlyactive,
 | 
        
           | 11 | efrain | 643 |             int $hascapability, ?bool $showonlyactiveenrolpref, array $expectedcount, array $expectedsumarray): void {
 | 
        
           | 1 | efrain | 644 |         global $CFG, $DB;
 | 
        
           |  |  | 645 |   | 
        
           |  |  | 646 |         $this->resetAfterTest();
 | 
        
           |  |  | 647 |   | 
        
           |  |  | 648 |         $CFG->grade_report_showonlyactiveenrol = $onlyactive;
 | 
        
           |  |  | 649 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 650 |   | 
        
           |  |  | 651 |         // Create users.
 | 
        
           |  |  | 652 |         $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']);
 | 
        
           |  |  | 653 |         $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']);
 | 
        
           |  |  | 654 |         $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']);
 | 
        
           |  |  | 655 |         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 | 
        
           |  |  | 656 |   | 
        
           |  |  | 657 |         // Enrol students.
 | 
        
           |  |  | 658 |         $this->getDataGenerator()->enrol_user($student1->id, $course->id, 'student');
 | 
        
           |  |  | 659 |         $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student');
 | 
        
           |  |  | 660 |   | 
        
           |  |  | 661 |         // Give teacher 'viewsuspendedusers' capability and set a preference to display suspended users.
 | 
        
           |  |  | 662 |         $roleteacher = $DB->get_record('role', ['shortname' => 'teacher'], '*', MUST_EXIST);
 | 
        
           |  |  | 663 |         $coursecontext = \context_course::instance($course->id);
 | 
        
           |  |  | 664 |         assign_capability('moodle/course:viewsuspendedusers', $hascapability, $roleteacher->id, $coursecontext, true);
 | 
        
           |  |  | 665 |         set_user_preference('grade_report_showonlyactiveenrol', $showonlyactiveenrolpref, $teacher);
 | 
        
           |  |  | 666 |         accesslib_clear_all_caches_for_unit_testing();
 | 
        
           |  |  | 667 |   | 
        
           |  |  | 668 |         $this->setUser($teacher);
 | 
        
           |  |  | 669 |   | 
        
           |  |  | 670 |         // Suspended student.
 | 
        
           |  |  | 671 |         $this->getDataGenerator()->enrol_user($student3->id, $course->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED);
 | 
        
           |  |  | 672 |   | 
        
           |  |  | 673 |         // Create grade items in course.
 | 
        
           |  |  | 674 |         $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([
 | 
        
           |  |  | 675 |             'itemname' => 'Grade item1',
 | 
        
           |  |  | 676 |             'idnumber' => 'git1',
 | 
        
           |  |  | 677 |             'courseid' => $course->id,
 | 
        
           |  |  | 678 |         ]));
 | 
        
           |  |  | 679 |   | 
        
           |  |  | 680 |         // Grade users.
 | 
        
           |  |  | 681 |         $manuaitem->update_final_grade($student1->id, 1);
 | 
        
           |  |  | 682 |         $manuaitem->update_final_grade($student3->id, 2);
 | 
        
           |  |  | 683 |   | 
        
           |  |  | 684 |         // Trigger a regrade.
 | 
        
           |  |  | 685 |         grade_force_full_regrading($course->id);
 | 
        
           |  |  | 686 |         grade_regrade_final_grades($course->id);
 | 
        
           |  |  | 687 |   | 
        
           |  |  | 688 |         // Initialise reports.
 | 
        
           |  |  | 689 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 690 |   | 
        
           |  |  | 691 |         $gpr = new grade_plugin_return(
 | 
        
           |  |  | 692 |             [
 | 
        
           |  |  | 693 |                 'type' => 'report',
 | 
        
           |  |  | 694 |                 'plugin' => 'grader',
 | 
        
           |  |  | 695 |                 'course' => $course,
 | 
        
           |  |  | 696 |             ]
 | 
        
           |  |  | 697 |         );
 | 
        
           |  |  | 698 |   | 
        
           |  |  | 699 |         $report = new grade_report_grader($course->id, $gpr, $context);
 | 
        
           |  |  | 700 |   | 
        
           |  |  | 701 |         $showonlyactiveenrol = $report->show_only_active();
 | 
        
           |  |  | 702 |         $ungradedcounts = $report->ungraded_counts(false, false, $showonlyactiveenrol);
 | 
        
           |  |  | 703 |   | 
        
           |  |  | 704 |         $gradeitems = grade_item::fetch_all(['courseid' => $course->id]);
 | 
        
           |  |  | 705 |   | 
        
           |  |  | 706 |         foreach ($gradeitems as $gradeitem) {
 | 
        
           |  |  | 707 |             $sumgrades = null;
 | 
        
           |  |  | 708 |             if (array_key_exists($gradeitem->id, $ungradedcounts['ungradedcounts'])) {
 | 
        
           |  |  | 709 |                 $ungradeditem = $ungradedcounts['ungradedcounts'][$gradeitem->id];
 | 
        
           |  |  | 710 |                 if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 711 |                     $this->assertEquals($expectedcount['course'], $ungradeditem->count);
 | 
        
           |  |  | 712 |                 } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 713 |                     $this->assertEquals($expectedcount['Grade item1'], $ungradeditem->count);
 | 
        
           |  |  | 714 |                 }
 | 
        
           |  |  | 715 |             }
 | 
        
           |  |  | 716 |   | 
        
           |  |  | 717 |             if (array_key_exists($gradeitem->id, $ungradedcounts['sumarray'])) {
 | 
        
           |  |  | 718 |                 $sumgrades = $ungradedcounts['sumarray'][$gradeitem->id];
 | 
        
           |  |  | 719 |                 if ($gradeitem->itemtype === 'course') {
 | 
        
           |  |  | 720 |                     $this->assertEquals($expectedsumarray['course'], $sumgrades);
 | 
        
           |  |  | 721 |                 } else if ($gradeitem->itemtype === 'manual') {
 | 
        
           |  |  | 722 |                     $this->assertEquals($expectedsumarray['Grade item1'], $sumgrades);
 | 
        
           |  |  | 723 |                 }
 | 
        
           |  |  | 724 |             }
 | 
        
           |  |  | 725 |         }
 | 
        
           |  |  | 726 |     }
 | 
        
           |  |  | 727 |   | 
        
           |  |  | 728 |     /**
 | 
        
           |  |  | 729 |      * Data provider for test_ungraded_counts_hidden_grades
 | 
        
           |  |  | 730 |      *
 | 
        
           |  |  | 731 |      * @return array of testing scenarios
 | 
        
           |  |  | 732 |      */
 | 
        
           |  |  | 733 |     public function ungraded_counts_only_active_enrol_data(): array {
 | 
        
           |  |  | 734 |         return [
 | 
        
           |  |  | 735 |             'Show only active and no user preference' => [
 | 
        
           |  |  | 736 |                 'onlyactive' => true,
 | 
        
           |  |  | 737 |                 'hascapability' => 1,
 | 
        
           |  |  | 738 |                 'showonlyactiveenrolpref' => null,
 | 
        
           |  |  | 739 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 740 |                 'sumarray' => ['course' => 1, 'Grade item1' => 1.00000],
 | 
        
           |  |  | 741 |             ],
 | 
        
           |  |  | 742 |             'Show only active and user preference set to true' => [
 | 
        
           |  |  | 743 |                 'onlyactive' => true,
 | 
        
           |  |  | 744 |                 'hascapability' => 1,
 | 
        
           |  |  | 745 |                 'showonlyactiveenrolpref' => true,
 | 
        
           |  |  | 746 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 747 |                 'sumarray' => ['course' => 1, 'Grade item1' => 1.00000],
 | 
        
           |  |  | 748 |             ],
 | 
        
           |  |  | 749 |             'Show only active and user preference set to false' => [
 | 
        
           |  |  | 750 |                 'onlyactive' => true,
 | 
        
           |  |  | 751 |                 'hascapability' => 1,
 | 
        
           |  |  | 752 |                 'showonlyactiveenrolpref' => false,
 | 
        
           |  |  | 753 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 754 |                 'sumarray' => ['course' => 3.00000, 'Grade item1' => 3.00000],
 | 
        
           |  |  | 755 |             ],
 | 
        
           |  |  | 756 |             'Include suspended with capability and user preference set to true' => [
 | 
        
           |  |  | 757 |                 'onlyactive' => false,
 | 
        
           |  |  | 758 |                 'hascapability' => 1,
 | 
        
           |  |  | 759 |                 'showonlyactiveenrolpref' => true,
 | 
        
           |  |  | 760 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 761 |                 'sumarray' => ['course' => 1.00000, 'Grade item1' => 1.00000],
 | 
        
           |  |  | 762 |             ],
 | 
        
           |  |  | 763 |             'Include suspended with capability and user preference set to false' => [
 | 
        
           |  |  | 764 |                 'onlyactive' => false,
 | 
        
           |  |  | 765 |                 'hascapability' => 1,
 | 
        
           |  |  | 766 |                 'showonlyactiveenrolpref' => false,
 | 
        
           |  |  | 767 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 768 |                 'sumarray' => ['course' => 3.00000, 'Grade item1' => 3.00000],
 | 
        
           |  |  | 769 |             ],
 | 
        
           |  |  | 770 |             'Include suspended with capability and no user preference' => [
 | 
        
           |  |  | 771 |                 'onlyactive' => false,
 | 
        
           |  |  | 772 |                 'hascapability' => 1,
 | 
        
           |  |  | 773 |                 'showonlyactiveenrolpref' => null,
 | 
        
           |  |  | 774 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 775 |                 'sumarray' => ['course' => 3.00000, 'Grade item1' => 3.00000],
 | 
        
           |  |  | 776 |             ],
 | 
        
           |  |  | 777 |             'Include suspended without capability' => [
 | 
        
           |  |  | 778 |                 'onlyactive' => false,
 | 
        
           |  |  | 779 |                 'hascapability' => -1,
 | 
        
           |  |  | 780 |                 'showonlyactiveenrolpref' => null,
 | 
        
           |  |  | 781 |                 'count' => ['course' => 1, 'Grade item1' => 1],
 | 
        
           |  |  | 782 |                 'sumarray' => ['course' => 1.00000, 'Grade item1' => 1.00000],
 | 
        
           |  |  | 783 |             ],
 | 
        
           |  |  | 784 |         ];
 | 
        
           |  |  | 785 |     }
 | 
        
           |  |  | 786 |   | 
        
           |  |  | 787 |     /**
 | 
        
           |  |  | 788 |      * Tests for calculate_average.
 | 
        
           |  |  | 789 |      * @dataProvider calculate_average_data()
 | 
        
           |  |  | 790 |      * @param int $meanselection Whether to inlcude all grades or non-empty grades in aggregation.
 | 
        
           |  |  | 791 |      * @param array $expectedmeancount expected meancount value
 | 
        
           |  |  | 792 |      * @param array $expectedaverage expceted average value
 | 
        
           |  |  | 793 |      *
 | 
        
           |  |  | 794 |      * @covers \grade_report::calculate_average
 | 
        
           |  |  | 795 |      */
 | 
        
           | 11 | efrain | 796 |     public function test_calculate_average(int $meanselection, array $expectedmeancount, array $expectedaverage): void {
 | 
        
           | 1 | efrain | 797 |         global $DB;
 | 
        
           |  |  | 798 |   | 
        
           |  |  | 799 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 800 |   | 
        
           |  |  | 801 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 802 |   | 
        
           |  |  | 803 |         $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']);
 | 
        
           |  |  | 804 |         $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']);
 | 
        
           |  |  | 805 |         $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']);
 | 
        
           |  |  | 806 |   | 
        
           |  |  | 807 |         $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
 | 
        
           |  |  | 808 |   | 
        
           |  |  | 809 |         // Enrol students.
 | 
        
           |  |  | 810 |         $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
 | 
        
           |  |  | 811 |         $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
 | 
        
           |  |  | 812 |         $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id);
 | 
        
           |  |  | 813 |   | 
        
           |  |  | 814 |         // Create activities.
 | 
        
           |  |  | 815 |         $assign1 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]);
 | 
        
           |  |  | 816 |         $assign2 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]);
 | 
        
           |  |  | 817 |         $quiz1 = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]);
 | 
        
           |  |  | 818 |   | 
        
           |  |  | 819 |         // Grade users.
 | 
        
           |  |  | 820 |         $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign1->id));
 | 
        
           |  |  | 821 |         $assigninstance = new assign($cm->context, $cm, $course);
 | 
        
           |  |  | 822 |         $grade = $assigninstance->get_user_grade($student1->id, true);
 | 
        
           |  |  | 823 |         $grade->grade = 40;
 | 
        
           |  |  | 824 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 825 |   | 
        
           |  |  | 826 |         $grade = $assigninstance->get_user_grade($student2->id, true);
 | 
        
           |  |  | 827 |         $grade->grade = 30;
 | 
        
           |  |  | 828 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 829 |   | 
        
           |  |  | 830 |         $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign2->id));
 | 
        
           |  |  | 831 |         $assigninstance = new assign($cm->context, $cm, $course);
 | 
        
           |  |  | 832 |         $grade = $assigninstance->get_user_grade($student3->id, true);
 | 
        
           |  |  | 833 |         $grade->grade = 50;
 | 
        
           |  |  | 834 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 835 |   | 
        
           |  |  | 836 |         $grade = $assigninstance->get_user_grade($student1->id, true);
 | 
        
           |  |  | 837 |         $grade->grade = 100;
 | 
        
           |  |  | 838 |         $assigninstance->update_grade($grade);
 | 
        
           |  |  | 839 |   | 
        
           |  |  | 840 |         // Make a manual grade items.
 | 
        
           |  |  | 841 |         $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([
 | 
        
           |  |  | 842 |             'itemname'        => 'Grade item1',
 | 
        
           |  |  | 843 |             'idnumber'        => 'git1',
 | 
        
           |  |  | 844 |             'courseid'        => $course->id,
 | 
        
           |  |  | 845 |         ]));
 | 
        
           |  |  | 846 |         $manuaitem->update_final_grade($student1->id, 1);
 | 
        
           |  |  | 847 |         $manuaitem->update_final_grade($student3->id, 2);
 | 
        
           |  |  | 848 |   | 
        
           |  |  | 849 |         // Initialise report.
 | 
        
           |  |  | 850 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 851 |   | 
        
           |  |  | 852 |         $gpr = new grade_plugin_return(
 | 
        
           |  |  | 853 |             [
 | 
        
           |  |  | 854 |                 'type' => 'report',
 | 
        
           |  |  | 855 |                 'plugin' => 'grader',
 | 
        
           |  |  | 856 |                 'course' => $course,
 | 
        
           |  |  | 857 |             ]
 | 
        
           |  |  | 858 |         );
 | 
        
           |  |  | 859 |   | 
        
           |  |  | 860 |         $report = new grade_report_grader($course->id, $gpr, $context);
 | 
        
           |  |  | 861 |   | 
        
           |  |  | 862 |         $ungradedcounts = $report->ungraded_counts(false);
 | 
        
           |  |  | 863 |         $ungradedcounts['report']['meanselection'] = $meanselection;
 | 
        
           |  |  | 864 |   | 
        
           |  |  | 865 |         $gradeitems = grade_item::fetch_all(['courseid' => $course->id]);
 | 
        
           |  |  | 866 |   | 
        
           |  |  | 867 |         foreach ($gradeitems as $gradeitem) {
 | 
        
           |  |  | 868 |             $name = $gradeitem->itemname . ' ' . $gradeitem->itemtype;
 | 
        
           |  |  | 869 |             $aggr = $report->calculate_average($gradeitem, $ungradedcounts);
 | 
        
           |  |  | 870 |   | 
        
           |  |  | 871 |             $this->assertEquals($expectedmeancount[$name], $aggr['meancount']);
 | 
        
           |  |  | 872 |             $this->assertEquals($expectedaverage[$name], $aggr['average']);
 | 
        
           |  |  | 873 |         }
 | 
        
           |  |  | 874 |     }
 | 
        
           |  |  | 875 |   | 
        
           |  |  | 876 |     /**
 | 
        
           |  |  | 877 |      * Data provider for test_calculate_average
 | 
        
           |  |  | 878 |      *
 | 
        
           |  |  | 879 |      * @return array of testing scenarios
 | 
        
           |  |  | 880 |      */
 | 
        
           |  |  | 881 |     public function calculate_average_data(): array {
 | 
        
           |  |  | 882 |         return [
 | 
        
           |  |  | 883 |             'Non-empty grades' => [
 | 
        
           |  |  | 884 |                 'meanselection' => 1,
 | 
        
           |  |  | 885 |                 'expectedmeancount' => [' course' => 3, 'Assignment 1 mod' => 2, 'Assignment 2 mod' => 2,
 | 
        
           |  |  | 886 |                     'Quiz 1 mod' => 0, 'Grade item1 manual' => 2],
 | 
        
           |  |  | 887 |                 'expectedaverage' => [' course' => 73.33333333333333, 'Assignment 1 mod' => 35.0,
 | 
        
           |  |  | 888 |                     'Assignment 2 mod' => 75.0, 'Quiz 1 mod' => null, 'Grade item1 manual' => 1.5],
 | 
        
           |  |  | 889 |             ],
 | 
        
           |  |  | 890 |             'All grades' => [
 | 
        
           |  |  | 891 |                 'meanselection' => 0,
 | 
        
           |  |  | 892 |                 'expectedmeancount' => [' course' => 3, 'Assignment 1 mod' => 3, 'Assignment 2 mod' => 3,
 | 
        
           |  |  | 893 |                     'Quiz 1 mod' => 3, 'Grade item1 manual' => 3],
 | 
        
           |  |  | 894 |                 'expectedaverage' => [' course' => 73.33333333333333, 'Assignment 1 mod' => 23.333333333333332,
 | 
        
           |  |  | 895 |                     'Assignment 2 mod' => 50.0, 'Quiz 1 mod' => null, 'Grade item1 manual' => 1.0],
 | 
        
           |  |  | 896 |             ],
 | 
        
           |  |  | 897 |         ];
 | 
        
           |  |  | 898 |     }
 | 
        
           |  |  | 899 |   | 
        
           |  |  | 900 |     /**
 | 
        
           |  |  | 901 |      * Tests for item types.
 | 
        
           |  |  | 902 |      *
 | 
        
           |  |  | 903 |      * @covers \grade_report::item_types
 | 
        
           |  |  | 904 |      */
 | 
        
           | 11 | efrain | 905 |     public function test_item_types(): void {
 | 
        
           | 1 | efrain | 906 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 907 |   | 
        
           |  |  | 908 |         $course1 = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 909 |         $course2 = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 910 |   | 
        
           |  |  | 911 |         // Create activities.
 | 
        
           |  |  | 912 |         $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]);
 | 
        
           |  |  | 913 |         $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]);
 | 
        
           |  |  | 914 |         $this->getDataGenerator()->create_module('quiz', ['course' => $course1->id]);
 | 
        
           |  |  | 915 |   | 
        
           |  |  | 916 |         $this->getDataGenerator()->create_module('assign', ['course' => $course2->id]);
 | 
        
           |  |  | 917 |   | 
        
           |  |  | 918 |         // Create manual grade items.
 | 
        
           |  |  | 919 |         new \grade_item($this->getDataGenerator()->create_grade_item([
 | 
        
           |  |  | 920 |             'itemname'        => 'Grade item1',
 | 
        
           |  |  | 921 |             'idnumber'        => 'git1',
 | 
        
           |  |  | 922 |             'courseid'        => $course1->id,
 | 
        
           |  |  | 923 |         ]));
 | 
        
           |  |  | 924 |   | 
        
           |  |  | 925 |         new \grade_item($this->getDataGenerator()->create_grade_item([
 | 
        
           |  |  | 926 |             'itemname'        => 'Grade item2',
 | 
        
           |  |  | 927 |             'idnumber'        => 'git2',
 | 
        
           |  |  | 928 |             'courseid'        => $course2->id,
 | 
        
           |  |  | 929 |         ]));
 | 
        
           |  |  | 930 |   | 
        
           |  |  | 931 |         // Create a grade category (it should not be fetched by item_types).
 | 
        
           |  |  | 932 |         new \grade_category($this->getDataGenerator()
 | 
        
           |  |  | 933 |             ->create_grade_category(['courseid' => $course1->id]), false);
 | 
        
           |  |  | 934 |   | 
        
           |  |  | 935 |         // Initialise reports.
 | 
        
           |  |  | 936 |         $context = \context_course::instance($course1->id);
 | 
        
           |  |  | 937 |   | 
        
           |  |  | 938 |         $gpr = new grade_plugin_return(
 | 
        
           |  |  | 939 |             [
 | 
        
           |  |  | 940 |                 'type' => 'report',
 | 
        
           |  |  | 941 |                 'plugin' => 'grader',
 | 
        
           |  |  | 942 |                 'course' => $course1,
 | 
        
           |  |  | 943 |             ]
 | 
        
           |  |  | 944 |         );
 | 
        
           |  |  | 945 |   | 
        
           |  |  | 946 |         $report1 = new grade_report_grader($course1->id, $gpr, $context);
 | 
        
           |  |  | 947 |   | 
        
           |  |  | 948 |         $context = \context_course::instance($course2->id);
 | 
        
           |  |  | 949 |   | 
        
           |  |  | 950 |         $gpr = new grade_plugin_return(
 | 
        
           |  |  | 951 |             [
 | 
        
           |  |  | 952 |                 'type' => 'report',
 | 
        
           |  |  | 953 |                 'plugin' => 'grader',
 | 
        
           |  |  | 954 |                 'course' => $course2,
 | 
        
           |  |  | 955 |             ]
 | 
        
           |  |  | 956 |         );
 | 
        
           |  |  | 957 |   | 
        
           |  |  | 958 |         $report2 = new grade_report_grader($course2->id, $gpr, $context);
 | 
        
           |  |  | 959 |   | 
        
           |  |  | 960 |         $gradeitems1 = $report1->item_types();
 | 
        
           |  |  | 961 |         $gradeitems2 = $report2->item_types();
 | 
        
           |  |  | 962 |   | 
        
           |  |  | 963 |         $this->assertEquals(3, count($gradeitems1));
 | 
        
           |  |  | 964 |         $this->assertEquals(2, count($gradeitems2));
 | 
        
           |  |  | 965 |   | 
        
           |  |  | 966 |         $this->assertArrayHasKey('assign', $gradeitems1);
 | 
        
           |  |  | 967 |         $this->assertArrayHasKey('quiz', $gradeitems1);
 | 
        
           |  |  | 968 |         $this->assertArrayHasKey('manual', $gradeitems1);
 | 
        
           |  |  | 969 |   | 
        
           |  |  | 970 |         $this->assertArrayHasKey('assign', $gradeitems2);
 | 
        
           |  |  | 971 |         $this->assertArrayHasKey('manual', $gradeitems2);
 | 
        
           |  |  | 972 |     }
 | 
        
           |  |  | 973 |   | 
        
           |  |  | 974 |     /**
 | 
        
           |  |  | 975 |      * Test get_gradable_users() function.
 | 
        
           |  |  | 976 |      *
 | 
        
           |  |  | 977 |      * @covers ::get_gradable_users
 | 
        
           |  |  | 978 |      */
 | 
        
           | 11 | efrain | 979 |     public function test_get_gradable_users(): void {
 | 
        
           | 1 | efrain | 980 |         global $DB;
 | 
        
           |  |  | 981 |   | 
        
           |  |  | 982 |         $this->setAdminUser();
 | 
        
           |  |  | 983 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 984 |   | 
        
           |  |  | 985 |         $roleteacher = $DB->get_record('role', ['shortname' => 'teacher'], '*', MUST_EXIST);
 | 
        
           |  |  | 986 |   | 
        
           |  |  | 987 |         // Create a course.
 | 
        
           |  |  | 988 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 989 |         $coursecontext = \context_course::instance($course->id);
 | 
        
           |  |  | 990 |         // Create groups.
 | 
        
           |  |  | 991 |         $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 | 
        
           |  |  | 992 |         $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 | 
        
           |  |  | 993 |         // Create and enrol a teacher and some students into the course.
 | 
        
           |  |  | 994 |         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 | 
        
           |  |  | 995 |         $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
 | 
        
           |  |  | 996 |         $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
 | 
        
           |  |  | 997 |         $student3 = $this->getDataGenerator()->create_and_enrol($course, 'student');
 | 
        
           |  |  | 998 |         // Add student1 and student2 to group1.
 | 
        
           |  |  | 999 |         $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $student1->id]);
 | 
        
           |  |  | 1000 |         $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $student2->id]);
 | 
        
           |  |  | 1001 |         // Add student3 to group2.
 | 
        
           |  |  | 1002 |         $this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $student3->id]);
 | 
        
           |  |  | 1003 |   | 
        
           |  |  | 1004 |         // Perform a regrade before creating the report.
 | 
        
           |  |  | 1005 |         grade_regrade_final_grades($course->id);
 | 
        
           |  |  | 1006 |         // Should return all gradable users (only students).
 | 
        
           |  |  | 1007 |         $gradableusers = get_gradable_users($course->id);
 | 
        
           |  |  | 1008 |         $this->assertEqualsCanonicalizing([$student1->id, $student2->id, $student3->id], array_keys($gradableusers));
 | 
        
           |  |  | 1009 |   | 
        
           |  |  | 1010 |         // Now, let's suspend the enrolment of student2.
 | 
        
           |  |  | 1011 |         $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED);
 | 
        
           |  |  | 1012 |         // Should return only the active gradable users (student1 and student3).
 | 
        
           |  |  | 1013 |         $gradableusers = \grade_report::get_gradable_users($course->id);
 | 
        
           |  |  | 1014 |         $this->assertEqualsCanonicalizing([$student1->id, $student3->id], array_keys($gradableusers));
 | 
        
           |  |  | 1015 |   | 
        
           |  |  | 1016 |         // Give teacher 'viewsuspendedusers' capability and set a preference to display suspended users.
 | 
        
           |  |  | 1017 |         assign_capability('moodle/course:viewsuspendedusers', CAP_ALLOW, $roleteacher->id, $coursecontext, true);
 | 
        
           |  |  | 1018 |         set_user_preference('grade_report_showonlyactiveenrol', false, $teacher);
 | 
        
           |  |  | 1019 |         accesslib_clear_all_caches_for_unit_testing();
 | 
        
           |  |  | 1020 |   | 
        
           |  |  | 1021 |         $this->setUser($teacher);
 | 
        
           |  |  | 1022 |         // Should return all gradable users (including suspended enrolments).
 | 
        
           |  |  | 1023 |         $gradableusers = \grade_report::get_gradable_users($course->id);
 | 
        
           |  |  | 1024 |         $this->assertEqualsCanonicalizing([$student1->id, $student2->id, $student3->id], array_keys($gradableusers));
 | 
        
           |  |  | 1025 |   | 
        
           |  |  | 1026 |         // Reactivate the course enrolment of student2.
 | 
        
           |  |  | 1027 |         $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student', 'manual', 0, 0, ENROL_USER_ACTIVE);
 | 
        
           |  |  | 1028 |         $this->setAdminUser();
 | 
        
           |  |  | 1029 |         // Should return all gradable users from group1 (student1 and student2).
 | 
        
           |  |  | 1030 |         $gradableusers = \grade_report::get_gradable_users($course->id, $group1->id);
 | 
        
           |  |  | 1031 |         $this->assertEqualsCanonicalizing([$student1->id, $student2->id], array_keys($gradableusers));
 | 
        
           |  |  | 1032 |         // Should return all gradable users from group2 (student3).
 | 
        
           |  |  | 1033 |         $gradableusers = \grade_report::get_gradable_users($course->id, $group2->id);
 | 
        
           |  |  | 1034 |         $this->assertEqualsCanonicalizing([$student3->id], array_keys($gradableusers));
 | 
        
           |  |  | 1035 |     }
 | 
        
           |  |  | 1036 | }
 |