See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [Versions 401 and 403]
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 declare(strict_types=1); 18 19 namespace core_course\reportbuilder\datasource; 20 21 use completion_completion; 22 use core_reportbuilder\local\filters\boolean_select; 23 use core_reportbuilder\local\filters\date; 24 use core_reportbuilder\local\filters\select; 25 use core_reportbuilder_generator; 26 use core_reportbuilder_testcase; 27 use grade_item; 28 29 defined('MOODLE_INTERNAL') || die(); 30 31 global $CFG; 32 require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); 33 require_once("{$CFG->libdir}/gradelib.php"); 34 35 /** 36 * Course participants datasource tests 37 * 38 * @package core_course 39 * @covers \core_course\reportbuilder\datasource\participants 40 * @covers \core_course\reportbuilder\local\formatters\completion 41 * @covers \core_course\reportbuilder\local\formatters\enrolment 42 * @copyright 2022 David Matamoros <davidmc@moodle.com> 43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 44 */ 45 class participants_test extends core_reportbuilder_testcase { 46 47 /** 48 * Test participants datasource 49 */ 50 public function test_participants_datasource(): void { 51 global $DB; 52 $this->resetAfterTest(); 53 54 $timestart = time() - DAYSECS; 55 $timeend = $timestart + 3 * DAYSECS; 56 $timecompleted = $timestart + 2 * DAYSECS; 57 $timelastaccess = time() + 4 * DAYSECS; 58 59 $category = $this->getDataGenerator()->create_category(['name' => 'Music']); 60 $course = $this->getDataGenerator()->create_course([ 61 'category' => $category->id, 62 'fullname' => 'All about Lionel at the work place', 63 'enablecompletion' => true, 64 'startdate' => $timestart, 65 'enddate' => $timeend, 66 ]); 67 68 $user1 = self::getDataGenerator()->create_user(); 69 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student', 70 'manual', $timestart, $timeend, ENROL_USER_ACTIVE); 71 72 // Add them to a group. 73 $group = self::getDataGenerator()->create_group(['courseid' => $course->id]); 74 self::getDataGenerator()->create_group_member(['groupid' => $group->id, 'userid' => $user1->id]); 75 76 // Mark course as completed for the user. 77 $ccompletion = new completion_completion(array('course' => $course->id, 'userid' => $user1->id)); 78 $ccompletion->mark_enrolled($timestart); 79 $ccompletion->mark_complete($timecompleted); 80 81 // Update final grade for the user. 82 $courseitem = grade_item::fetch_course_item($course->id); 83 $courseitem->update_final_grade($user1->id, 42.5); 84 85 // Set some last access value for the user in the course. 86 $DB->insert_record('user_lastaccess', 87 ['userid' => $user1->id, 'courseid' => $course->id, 'timeaccess' => $timelastaccess]); 88 89 /** @var core_reportbuilder_generator $generator */ 90 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 91 $report = $generator->create_report(['name' => 'Courses', 'source' => participants::class, 'default' => false]); 92 93 $generator->create_column(['reportid' => $report->get('id'), 94 'uniqueidentifier' => 'course:fullname']); 95 $generator->create_column(['reportid' => $report->get('id'), 96 'uniqueidentifier' => 'course_category:name']); 97 $generator->create_column(['reportid' => $report->get('id'), 98 'uniqueidentifier' => 'user:fullname']); 99 // Order by enrolment method. 100 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'enrolment:method', 'sortenabled' => 1]); 101 $generator->create_column(['reportid' => $report->get('id'), 102 'uniqueidentifier' => 'group:name']); 103 $generator->create_column(['reportid' => $report->get('id'), 104 'uniqueidentifier' => 'completion:completed']); 105 $generator->create_column(['reportid' => $report->get('id'), 106 'uniqueidentifier' => 'access:timeaccess']); 107 $generator->create_column(['reportid' => $report->get('id'), 108 'uniqueidentifier' => 'completion:progresspercent']); 109 $generator->create_column(['reportid' => $report->get('id'), 110 'uniqueidentifier' => 'completion:timeenrolled']); 111 $generator->create_column(['reportid' => $report->get('id'), 112 'uniqueidentifier' => 'completion:timestarted']); 113 $generator->create_column(['reportid' => $report->get('id'), 114 'uniqueidentifier' => 'completion:timecompleted']); 115 $generator->create_column(['reportid' => $report->get('id'), 116 'uniqueidentifier' => 'completion:reaggregate']); 117 $generator->create_column(['reportid' => $report->get('id'), 118 'uniqueidentifier' => 'completion:dayscourse']); 119 $generator->create_column(['reportid' => $report->get('id'), 120 'uniqueidentifier' => 'completion:daysuntilcompletion']); 121 $generator->create_column(['reportid' => $report->get('id'), 122 'uniqueidentifier' => 'completion:grade']); 123 124 // Add filter to the report. 125 $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'enrolment:method']); 126 127 $content = $this->get_custom_report_content($report->get('id')); 128 129 // It should get 3 records (manual enrolment, self and guest). 130 $this->assertCount(3, $content); 131 132 // Filter by Manual enrolment method. 133 $content = $this->get_custom_report_content($report->get('id'), 30, [ 134 'enrolment:method_operator' => select::EQUAL_TO, 135 'enrolment:method_value' => 'manual', 136 ]); 137 138 $this->assertCount(1, $content); 139 140 $this->assertEquals([ 141 'All about Lionel at the work place', // Course name. 142 'Music', // Course category name. 143 fullname($user1), // User fullname. 144 'Manual enrolments', // Enrolment method. 145 $group->name, // Group name. 146 'Yes', // Course completed. 147 userdate($timelastaccess), // Time last access. 148 '100.0%', // Progress percentage. 149 userdate($timestart), // Time enrolled. 150 '', // Time started. 151 userdate($timecompleted), // Time completed. 152 '', // Reagreggate. 153 '2', // Days taking course. 154 '2', // Days until completion. 155 '42.50', // Grade. 156 ], array_values($content[0])); 157 } 158 159 /** 160 * Data provider for {@see test_report_filters} 161 * 162 * @return array 163 */ 164 public function filters_data_provider(): array { 165 return [ 166 [ 167 'enrolment:status', 168 [ 169 'enrolment:status_operator' => select::EQUAL_TO, 170 'enrolment:status_value' => 1, 171 ], 172 'Luna' 173 ], 174 [ 175 'enrolment:timecreated', 176 [ 177 'enrolment:timecreated_operator' => date::DATE_CURRENT, 178 'enrolment:timecreated_unit' => date::DATE_UNIT_DAY, 179 ], 180 'Kira' 181 ], 182 [ 183 'enrolment:timestarted', 184 [ 185 'enrolment:timestarted_operator' => date::DATE_CURRENT, 186 'enrolment:timecreated_unit' => date::DATE_UNIT_DAY, 187 ], 188 'Luna' 189 ], 190 [ 191 'enrolment:timeended', 192 [ 193 'enrolment:timeended_operator' => date::DATE_CURRENT, 194 'enrolment:timeended_unit' => date::DATE_UNIT_DAY, 195 ], 196 'Luna' 197 ], 198 [ 199 'completion:completed', 200 [ 201 'completion:completed_operator' => boolean_select::CHECKED, 202 'completion:completed_unit' => 1, 203 ], 204 'Lionel' 205 ], 206 [ 207 'completion:timecompleted', 208 [ 209 'completion:timecompleted_operator' => date::DATE_NOT_EMPTY, 210 ], 211 'Lionel' 212 ], 213 ]; 214 } 215 216 /** 217 * Test getting filter SQL 218 * 219 * @param string $filter 220 * @param array $filtervalues 221 * @param string $expected 222 * 223 * @dataProvider filters_data_provider 224 */ 225 public function test_report_filters(string $filter, array $filtervalues, string $expected): void { 226 global $DB; 227 $this->resetAfterTest(); 228 229 $timestart = time() - DAYSECS; 230 $timeend = $timestart + 3 * DAYSECS; 231 $timecompleted = $timestart + 2 * DAYSECS; 232 $timelastaccess = time() + 4 * DAYSECS; 233 234 $category = $this->getDataGenerator()->create_category(['name' => 'Music']); 235 $course = $this->getDataGenerator()->create_course([ 236 'category' => $category->id, 237 'fullname' => 'All about Lionel at the work place', 238 'enablecompletion' => true, 239 'startdate' => $timestart, 240 'enddate' => $timeend, 241 ]); 242 243 $user1 = self::getDataGenerator()->create_user(['firstname' => 'Lionel']); 244 $user2 = self::getDataGenerator()->create_user(['firstname' => 'Kira']); 245 $user3 = self::getDataGenerator()->create_user(['firstname' => 'Luna']); 246 247 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student', 248 'manual', $timestart - 8 * DAYSECS, $timeend, ENROL_USER_ACTIVE); 249 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student', 250 'manual', $timestart, $timeend, ENROL_USER_ACTIVE); 251 $this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student', 252 'manual', time(), time(), ENROL_USER_SUSPENDED); 253 254 // Mark course as completed for the user. 255 $ccompletion = new completion_completion(array('course' => $course->id, 'userid' => $user1->id)); 256 $ccompletion->mark_enrolled($timestart); 257 $ccompletion->mark_complete($timecompleted); 258 259 // Set some last access value for the user in the course. 260 $DB->insert_record('user_lastaccess', 261 ['userid' => $user1->id, 'courseid' => $course->id, 'timeaccess' => $timelastaccess]); 262 263 /** @var core_reportbuilder_generator $generator */ 264 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 265 $report = $generator->create_report(['name' => 'Courses', 'source' => participants::class, 'default' => false]); 266 267 // Add user firstname column to the report. 268 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']); 269 270 $DB->set_field('user_enrolments', 'timecreated', 0, ['userid' => $user1->id]); 271 $DB->set_field('user_enrolments', 'timecreated', 0, ['userid' => $user3->id]); 272 273 // Add filters to the report. 274 $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'enrolment:method']); 275 $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filter]); 276 277 // Apply filters. 278 $filtermanual = ['enrolment:method_operator' => select::EQUAL_TO, 'enrolment:method_value' => 'manual']; 279 $content = $this->get_custom_report_content($report->get('id'), 30, $filtermanual + $filtervalues); 280 281 $this->assertCount(1, $content); 282 $this->assertEquals($expected, $content[0]['c0_firstname']); 283 } 284 285 /** 286 * Stress test datasource 287 * 288 * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php 289 */ 290 public function test_stress_datasource(): void { 291 if (!PHPUNIT_LONGTEST) { 292 $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); 293 } 294 295 $this->resetAfterTest(); 296 297 $course = $this->getDataGenerator()->create_course(); 298 $this->getDataGenerator()->create_and_enrol($course); 299 300 $this->datasource_stress_test_columns(participants::class); 301 $this->datasource_stress_test_columns_aggregation(participants::class); 302 $this->datasource_stress_test_conditions(participants::class, 'course:idnumber'); 303 } 304 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body