Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 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 core_customfield_generator; 22 use core_reportbuilder_testcase; 23 use core_reportbuilder_generator; 24 use core_reportbuilder\local\filters\boolean_select; 25 use core_reportbuilder\local\filters\date; 26 use core_reportbuilder\local\filters\select; 27 use core_reportbuilder\local\filters\text; 28 use core_reportbuilder\local\helpers\user_filter_manager; 29 30 defined('MOODLE_INTERNAL') || die(); 31 32 global $CFG; 33 require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); 34 35 /** 36 * Unit tests for component datasources 37 * 38 * @package core_course 39 * @covers \core_course\reportbuilder\datasource\courses 40 * @copyright 2021 Paul Holden <paulh@moodle.com> 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 class courses_test extends core_reportbuilder_testcase { 44 45 /** 46 * Test default datasource 47 */ 48 public function test_datasource_default(): void { 49 $this->resetAfterTest(); 50 51 // Test subject. 52 $category = $this->getDataGenerator()->create_category(['name' => 'My cats']); 53 $course = $this->getDataGenerator()->create_course([ 54 'category' => $category->id, 55 'fullname' => 'All about cats', 56 'shortname' => 'C101', 57 'idnumber' => 'CAT101' 58 ]); 59 60 /** @var core_reportbuilder_generator $generator */ 61 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 62 $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 1]); 63 64 $content = $this->get_custom_report_content($report->get('id')); 65 $this->assertCount(1, $content); 66 67 $contentrow = array_values($content[0]); 68 69 $this->assertEquals([ 70 $category->get_formatted_name(), 71 $course->shortname, 72 $course->fullname, 73 $course->idnumber, 74 ], $contentrow); 75 } 76 77 /** 78 * Test datasource columns that aren't added by default 79 */ 80 public function test_datasource_non_default_columns(): void { 81 $this->resetAfterTest(); 82 83 $category = $this->getDataGenerator()->create_category([ 84 'name' => 'Animals', 85 'idnumber' => 'CAT101', 86 'description' => 'Category description', 87 ]); 88 $course = $this->getDataGenerator()->create_course([ 89 'category' => $category->id, 90 'fullname' => 'Cats', 91 'summary' => 'Course description', 92 ]); 93 94 /** @var core_reportbuilder_generator $generator */ 95 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 96 $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]); 97 98 // Category. 99 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:path']); 100 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:idnumber']); 101 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:description']); 102 103 // Course. 104 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:coursefullnamewithlink']); 105 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:courseshortnamewithlink']); 106 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:courseidnumberewithlink']); 107 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:summary']); 108 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:format']); 109 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:startdate']); 110 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:enddate']); 111 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:visible']); 112 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:groupmode']); 113 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:groupmodeforce']); 114 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:lang']); 115 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:calendartype']); 116 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:theme']); 117 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:enablecompletion']); 118 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:downloadcontent']); 119 120 $content = $this->get_custom_report_content($report->get('id')); 121 $this->assertCount(1, $content); 122 123 $courserow = array_values($content[0]); 124 125 // Category. 126 $this->assertEquals($category->get_nested_name(false), $courserow[0]); 127 $this->assertEquals($category->idnumber, $courserow[1]); 128 $this->assertEquals(format_text($category->description, $category->descriptionformat), $courserow[2]); 129 130 // Course. 131 $this->assertStringContainsString($course->fullname, $courserow[3]); 132 $this->assertStringContainsString($course->shortname, $courserow[4]); 133 $this->assertStringContainsString($course->idnumber, $courserow[5]); 134 $this->assertEquals(format_text($course->summary, $course->summaryformat), $courserow[6]); 135 $this->assertEquals('Topics format', $courserow[7]); 136 $this->assertEquals(userdate($course->startdate), $courserow[8]); 137 $this->assertEmpty($courserow[9]); 138 $this->assertEquals('Yes', $courserow[10]); 139 $this->assertEquals('No groups', $courserow[11]); 140 $this->assertEquals('No', $courserow[12]); 141 $this->assertEmpty($courserow[13]); 142 $this->assertEmpty($courserow[14]); 143 $this->assertEmpty($courserow[15]); 144 $this->assertEquals('No', $courserow[16]); 145 $this->assertEmpty($courserow[17]); 146 } 147 148 /** 149 * Tests courses datasource using multilang filters 150 */ 151 public function test_courses_datasource_multilang_filters(): void { 152 $this->resetAfterTest(); 153 154 filter_set_global_state('multilang', TEXTFILTER_ON); 155 filter_set_applies_to_strings('multilang', true); 156 157 // Test subject. 158 $category = $this->getDataGenerator()->create_category([ 159 'name' => '<span class="multilang" lang="en">Cat (en)</span><span class="multilang" lang="es">Cat (es)</span>', 160 ]); 161 $course = $this->getDataGenerator()->create_course([ 162 'category' => $category->id, 163 'fullname' => '<span class="multilang" lang="en">Crs (en)</span><span class="multilang" lang="es">Crs (es)</span>', 164 ]); 165 166 /** @var core_reportbuilder_generator $generator */ 167 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 168 169 // Create a report containing columns that support multilang content. 170 $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]); 171 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:name']); 172 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']); 173 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:coursefullnamewithlink']); 174 175 $content = $this->get_custom_report_content($report->get('id')); 176 $this->assertCount(1, $content); 177 178 $contentrow = array_values(reset($content)); 179 $this->assertEquals([ 180 'Cat (en)', 181 'Crs (en)', 182 '<a href="' . (string) course_get_url($course->id) . '">Crs (en)</a>', 183 ], $contentrow); 184 } 185 186 /** 187 * Data provider for {@see test_datasource_filters} 188 * 189 * @return array[] 190 */ 191 public function datasource_filters_provider(): array { 192 return [ 193 // Category. 194 'Filter category' => ['course_category:name', [ 195 'course_category:name_operator' => select::EQUAL_TO, 196 'course_category:name_value' => -1, 197 ], false], 198 'Filter category idnumber' => ['course_category:idnumber', [ 199 'course_category:idnumber_operator' => text::IS_EQUAL_TO, 200 'course_category:idnumber_value' => 'CAT101', 201 ], true], 202 'Filter category idnumber (no match)' => ['course_category:idnumber', [ 203 'course_category:idnumber_operator' => text::CONTAINS, 204 'course_category:idnumber_value' => 'FRUIT', 205 ], false], 206 207 // Course. 208 'Filter course' => ['course:courseselector', [ 209 'course:courseselector_values' => [-1], 210 ], false], 211 'Filter course fullname' => ['course:fullname', [ 212 'course:fullname_operator' => text::IS_EQUAL_TO, 213 'course:fullname_value' => 'Equine', 214 ], true], 215 'Filter course fullname (no match)' => ['course:fullname', [ 216 'course:fullname_operator' => text::IS_EQUAL_TO, 217 'course:fullname_value' => 'Foxes', 218 ], false], 219 'Filter course shortname' => ['course:shortname', [ 220 'course:shortname_operator' => text::IS_EQUAL_TO, 221 'course:shortname_value' => 'EQ101', 222 ], true], 223 'Filter course shortname (no match)' => ['course:shortname', [ 224 'course:shortname_operator' => text::IS_EQUAL_TO, 225 'course:shortname_value' => 'FX101', 226 ], false], 227 'Filter course idnumber' => ['course:idnumber', [ 228 'course:idnumber_operator' => text::IS_EQUAL_TO, 229 'course:idnumber_value' => 'E-101AB', 230 ], true], 231 'Filter course idnumber (no match)' => ['course:idnumber', [ 232 'course:idnumber_operator' => text::IS_EQUAL_TO, 233 'course:idnumber_value' => 'F-101XT', 234 ], false], 235 'Filter course format' => ['course:format', [ 236 'course:format_operator' => select::EQUAL_TO, 237 'course:format_value' => 'topics', 238 ], true], 239 'Filter course format (no match)' => ['course:format', [ 240 'course:format_operator' => select::EQUAL_TO, 241 'course:format_value' => 'weekly', 242 ], false], 243 'Filter course startdate' => ['course:startdate', [ 244 'course:startdate_operator' => date::DATE_RANGE, 245 'course:startdate_from' => 1622502000, 246 ], true], 247 'Filter course startdate (no match)' => ['course:startdate', [ 248 'course:startdate_operator' => date::DATE_RANGE, 249 'course:startdate_to' => 1622502000, 250 ], false], 251 'Filter course enddate' => ['course:enddate', [ 252 'course:enddate_operator' => date::DATE_EMPTY, 253 ], true], 254 'Filter course enddate (no match)' => ['course:enddate', [ 255 'course:enddate_operator' => date::DATE_NOT_EMPTY, 256 ], false], 257 'Filter course visible' => ['course:visible', [ 258 'course:visible_operator' => boolean_select::CHECKED, 259 ], true], 260 'Filter course visible (no match)' => ['course:visible', [ 261 'course:visible_operator' => boolean_select::NOT_CHECKED, 262 ], false], 263 'Filter course groupmode' => ['course:groupmode', [ 264 'course:groupmode_operator' => select::EQUAL_TO, 265 'course:groupmode_value' => 0, // No groups. 266 ], true], 267 'Filter course groupmode (no match)' => ['course:groupmode', [ 268 'course:groupmode_operator' => select::EQUAL_TO, 269 'course:groupmode_value' => 1, // Separate groups. 270 ], false], 271 'Filter course groupmodeforce' => ['course:groupmodeforce', [ 272 'course:groupmodeforce_operator' => boolean_select::NOT_CHECKED, 273 ], true], 274 'Filter course groupmodeforce (no match)' => ['course:groupmodeforce', [ 275 'course:groupmodeforce_operator' => boolean_select::CHECKED, 276 ], false], 277 'Filter course lang' => ['course:lang', [ 278 'course:lang_operator' => select::EQUAL_TO, 279 'course:lang_value' => 'en', 280 ], true], 281 'Filter course lang (no match)' => ['course:lang', [ 282 'course:lang_operator' => select::EQUAL_TO, 283 'course:lang_value' => 'de', 284 ], false], 285 'Filter course calendartype' => ['course:calendartype', [ 286 'course:calendartype_operator' => select::EQUAL_TO, 287 'course:calendartype_value' => 'gregorian', 288 ], true], 289 'Filter course calendartype (no match)' => ['course:calendartype', [ 290 'course:calendartype_operator' => select::EQUAL_TO, 291 'course:calendartype_value' => 'hijri', 292 ], false], 293 'Filter course theme' => ['course:theme', [ 294 'course:theme_operator' => select::EQUAL_TO, 295 'course:theme_value' => 'boost', 296 ], true], 297 'Filter course theme (no match)' => ['course:theme', [ 298 'course:theme_operator' => select::EQUAL_TO, 299 'course:theme_value' => 'classic', 300 ], false], 301 'Filter course enablecompletion' => ['course:enablecompletion', [ 302 'course:enablecompletion_operator' => boolean_select::NOT_CHECKED, 303 ], true], 304 'Filter course enablecompletion (no match)' => ['course:enablecompletion', [ 305 'course:enablecompletion_operator' => boolean_select::CHECKED, 306 ], false], 307 'Filter course downloadcontent' => ['course:downloadcontent', [ 308 'course:downloadcontent_operator' => boolean_select::CHECKED, 309 ], true], 310 'Filter course downloadcontent (no match)' => ['course:downloadcontent', [ 311 'course:downloadcontent_operator' => boolean_select::NOT_CHECKED, 312 ], false], 313 ]; 314 } 315 316 /** 317 * Test datasource filters 318 * 319 * @param string $filtername 320 * @param array $filtervalues 321 * @param bool $expectmatch 322 * 323 * @dataProvider datasource_filters_provider 324 */ 325 public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void { 326 $this->resetAfterTest(); 327 328 $category = $this->getDataGenerator()->create_category(['name' => 'Animals', 'idnumber' => 'CAT101']); 329 $course = $this->getDataGenerator()->create_course([ 330 'category' => $category->id, 331 'fullname' => 'Equine', 332 'shortname' => 'EQ101', 333 'idnumber' => 'E-101AB', 334 'lang' => 'en', 335 'calendartype' => 'gregorian', 336 'theme' => 'boost', 337 'downloadcontent' => 1, 338 ]); 339 340 /** @var core_reportbuilder_generator $generator */ 341 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 342 343 // Create report containing single column, and given filter. 344 $report = $generator->create_report(['name' => 'Tasks', 'source' => courses::class, 'default' => 0]); 345 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']); 346 347 // Add filter, set it's values. 348 $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]); 349 user_filter_manager::set($report->get('id'), $filtervalues); 350 351 $content = $this->get_custom_report_content($report->get('id')); 352 353 if ($expectmatch) { 354 $this->assertCount(1, $content); 355 $this->assertEquals($course->fullname, reset($content[0])); 356 } else { 357 $this->assertEmpty($content); 358 } 359 } 360 361 /** 362 * Stress test datasource 363 * 364 * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php 365 */ 366 public function test_stress_datasource(): void { 367 if (!PHPUNIT_LONGTEST) { 368 $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); 369 } 370 371 $this->resetAfterTest(); 372 373 /** @var core_customfield_generator $generator */ 374 $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield'); 375 $customfieldcategory = $generator->create_category(); 376 $generator->create_field(['categoryid' => $customfieldcategory->get('id'), 'shortname' => 'hi']); 377 378 $category = $this->getDataGenerator()->create_category(); 379 $course = $this->getDataGenerator()->create_course(['category' => $category->id, 'customfield_hi' => 'Hello']); 380 381 $this->datasource_stress_test_columns(courses::class); 382 $this->datasource_stress_test_columns_aggregation(courses::class); 383 $this->datasource_stress_test_conditions(courses::class, 'course:idnumber'); 384 } 385 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body