Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 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_user\reportbuilder\datasource; 20 21 use core_reportbuilder_testcase; 22 use core_reportbuilder_generator; 23 use core_reportbuilder\local\filters\boolean_select; 24 use core_reportbuilder\local\filters\date; 25 use core_reportbuilder\local\filters\select; 26 use core_reportbuilder\local\filters\tags; 27 use core_reportbuilder\local\filters\text; 28 use core_reportbuilder\local\filters\user as user_filter; 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 users datasource 37 * 38 * @package core_user 39 * @covers \core_user\reportbuilder\datasource\users 40 * @copyright 2022 Paul Holden <paulh@moodle.com> 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 class users_test extends core_reportbuilder_testcase { 44 45 /** 46 * Test default datasource 47 */ 48 public function test_datasource_default(): void { 49 $this->resetAfterTest(); 50 51 $user2 = $this->getDataGenerator()->create_user(['firstname' => 'Charles']); 52 $user3 = $this->getDataGenerator()->create_user(['firstname' => 'Brian']); 53 54 /** @var core_reportbuilder_generator $generator */ 55 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 56 $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 1]); 57 58 $content = $this->get_custom_report_content($report->get('id')); 59 $this->assertCount(3, $content); 60 61 // Default columns are fullname, username, email. Results are sorted by the fullname. 62 [$adminrow, $userrow1, $userrow2] = array_map('array_values', $content); 63 64 $this->assertEquals(['Admin User', 'admin', 'admin@example.com'], $adminrow); 65 $this->assertEquals([fullname($user3), $user3->username, $user3->email], $userrow1); 66 $this->assertEquals([fullname($user2), $user2->username, $user2->email], $userrow2); 67 } 68 69 /** 70 * Test datasource columns that aren't added by default 71 */ 72 public function test_datasource_non_default_columns(): void { 73 $this->resetAfterTest(); 74 75 $user = $this->getDataGenerator()->create_user([ 76 'firstname' => 'Zoe', 77 'idnumber' => 'U0001', 78 'city' => 'London', 79 'country' => 'GB', 80 'interests' => ['Horses'], 81 ]); 82 83 /** @var core_reportbuilder_generator $generator */ 84 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 85 $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]); 86 87 // User. 88 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullnamewithlink', 89 'sortenabled' => 1]); 90 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullnamewithpicture']); 91 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullnamewithpicturelink']); 92 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:picture']); 93 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']); 94 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:lastname']); 95 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:city']); 96 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:country']); 97 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:description']); 98 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstnamephonetic']); 99 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:lastnamephonetic']); 100 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:middlename']); 101 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:alternatename']); 102 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:idnumber']); 103 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:institution']); 104 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:department']); 105 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:phone1']); 106 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:phone2']); 107 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:address']); 108 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:lastaccess']); 109 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:suspended']); 110 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:confirmed']); 111 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:moodlenetprofile']); 112 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:timecreated']); 113 114 // Tags. 115 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:name']); 116 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:namewithlink']); 117 118 $content = $this->get_custom_report_content($report->get('id')); 119 $this->assertCount(2, $content); 120 121 [$adminrow, $userrow] = array_map('array_values', $content); 122 123 $this->assertStringContainsString('Admin User', $adminrow[0]); 124 $this->assertStringContainsString('Admin User', $adminrow[1]); 125 $this->assertStringContainsString('Admin User', $adminrow[2]); 126 $this->assertNotEmpty($adminrow[3]); 127 $this->assertEquals('Admin', $adminrow[4]); 128 $this->assertEquals('User', $adminrow[5]); 129 130 $this->assertStringContainsString(fullname($user), $userrow[0]); 131 $this->assertStringContainsString(fullname($user), $userrow[1]); 132 $this->assertStringContainsString(fullname($user), $userrow[2]); 133 $this->assertNotEmpty($userrow[3]); 134 $this->assertEquals($user->firstname, $userrow[4]); 135 $this->assertEquals($user->lastname, $userrow[5]); 136 $this->assertEquals($user->city, $userrow[6]); 137 $this->assertEquals('United Kingdom', $userrow[7]); 138 $this->assertEquals($user->description, $userrow[8]); 139 $this->assertEquals($user->firstnamephonetic, $userrow[9]); 140 $this->assertEquals($user->lastnamephonetic, $userrow[10]); 141 $this->assertEquals($user->middlename, $userrow[11]); 142 $this->assertEquals($user->alternatename, $userrow[12]); 143 $this->assertEquals($user->idnumber, $userrow[13]); 144 $this->assertEquals($user->institution, $userrow[14]); 145 $this->assertEquals($user->department, $userrow[15]); 146 $this->assertEquals($user->phone1, $userrow[16]); 147 $this->assertEquals($user->phone2, $userrow[17]); 148 $this->assertEquals($user->address, $userrow[18]); 149 $this->assertEmpty($userrow[19]); 150 $this->assertEquals('No', $userrow[20]); 151 $this->assertEquals('Yes', $userrow[21]); 152 $this->assertEquals($user->moodlenetprofile, $userrow[22]); 153 $this->assertNotEmpty($userrow[23]); 154 $this->assertEquals('Horses', $userrow[24]); 155 $this->assertStringContainsString('Horses', $userrow[25]); 156 } 157 158 /** 159 * Data provider for {@see test_datasource_filters} 160 * 161 * @return array[] 162 */ 163 public function datasource_filters_provider(): array { 164 return [ 165 // User. 166 'Filter user' => ['user:userselect', [ 167 'user:userselect_operator' => user_filter::USER_SELECT, 168 'user:userselect_value' => [-1], 169 ], false], 170 'Filter fullname' => ['user:fullname', [ 171 'user:fullname_operator' => text::CONTAINS, 172 'user:fullname_value' => 'Zoe', 173 ], true], 174 'Filter fullname (no match)' => ['user:fullname', [ 175 'user:fullname_operator' => text::CONTAINS, 176 'user:fullname_value' => 'Alfie', 177 ], false], 178 'Filter firstname' => ['user:firstname', [ 179 'user:firstname_operator' => text::IS_EQUAL_TO, 180 'user:firstname_value' => 'Zoe', 181 ], true], 182 'Filter firstname (no match)' => ['user:firstname', [ 183 'user:firstname_operator' => text::IS_EQUAL_TO, 184 'user:firstname_value' => 'Alfie', 185 ], false], 186 'Filter middlename' => ['user:middlename', [ 187 'user:middlename_operator' => text::IS_EQUAL_TO, 188 'user:middlename_value' => 'Zebediah', 189 ], true], 190 'Filter middlename (no match)' => ['user:middlename', [ 191 'user:middlename_operator' => text::IS_EQUAL_TO, 192 'user:middlename_value' => 'Aardvark', 193 ], false], 194 'Filter lastname' => ['user:lastname', [ 195 'user:lastname_operator' => text::IS_EQUAL_TO, 196 'user:lastname_value' => 'Zebra', 197 ], true], 198 'Filter lastname (no match)' => ['user:lastname', [ 199 'user:lastname_operator' => text::IS_EQUAL_TO, 200 'user:lastname_value' => 'Aardvark', 201 ], false], 202 'Filter firstnamephonetic' => ['user:firstnamephonetic', [ 203 'user:firstnamephonetic_operator' => text::IS_EQUAL_TO, 204 'user:firstnamephonetic_value' => 'Eoz', 205 ], true], 206 'Filter firstnamephonetic (no match)' => ['user:firstnamephonetic', [ 207 'user:firstnamephonetic_operator' => text::IS_EQUAL_TO, 208 'user:firstnamephonetic_value' => 'Alfie', 209 ], false], 210 'Filter lastnamephonetic' => ['user:lastnamephonetic', [ 211 'user:lastnamephonetic_operator' => text::IS_EQUAL_TO, 212 'user:lastnamephonetic_value' => 'Arbez', 213 ], true], 214 'Filter lastnamephonetic (no match)' => ['user:lastnamephonetic', [ 215 'user:lastnamephonetic_operator' => text::IS_EQUAL_TO, 216 'user:lastnamephonetic_value' => 'Aardvark', 217 ], false], 218 'Filter alternatename' => ['user:alternatename', [ 219 'user:alternatename_operator' => text::IS_EQUAL_TO, 220 'user:alternatename_value' => 'Zee', 221 ], true], 222 'Filter alternatename (no match)' => ['user:alternatename', [ 223 'user:alternatename_operator' => text::IS_EQUAL_TO, 224 'user:alternatename_value' => 'Aardvark', 225 ], false], 226 'Filter email' => ['user:email', [ 227 'user:email_operator' => text::CONTAINS, 228 'user:email_value' => 'zoe1', 229 ], true], 230 'Filter email (no match)' => ['user:email', [ 231 'user:email_operator' => text::CONTAINS, 232 'user:email_value' => 'alfie1', 233 ], false], 234 'Filter phone1' => ['user:phone1', [ 235 'user:phone1_operator' => text::IS_EQUAL_TO, 236 'user:phone1_value' => '111', 237 ], true], 238 'Filter phone1 (no match)' => ['user:phone1', [ 239 'user:phone1_operator' => text::IS_EQUAL_TO, 240 'user:phone1_value' => '119', 241 ], false], 242 'Filter phone2' => ['user:phone2', [ 243 'user:phone2_operator' => text::IS_EQUAL_TO, 244 'user:phone2_value' => '222', 245 ], true], 246 'Filter phone2 (no match)' => ['user:phone2', [ 247 'user:phone2_operator' => text::IS_EQUAL_TO, 248 'user:phone2_value' => '229', 249 ], false], 250 'Filter address' => ['user:address', [ 251 'user:address_operator' => text::IS_EQUAL_TO, 252 'user:address_value' => 'Big Farm', 253 ], true], 254 'Filter address (no match)' => ['user:address', [ 255 'user:address_operator' => text::IS_EQUAL_TO, 256 'user:address_value' => 'Small Farm', 257 ], false], 258 259 'Filter city' => ['user:city', [ 260 'user:city_operator' => text::IS_EQUAL_TO, 261 'user:city_value' => 'Barcelona', 262 ], true], 263 'Filter city (no match)' => ['user:city', [ 264 'user:city_operator' => text::IS_EQUAL_TO, 265 'user:city_value' => 'Perth', 266 ], false], 267 'Filter country' => ['user:country', [ 268 'user:country_operator' => select::EQUAL_TO, 269 'user:country_value' => 'ES', 270 ], true], 271 'Filter country (no match)' => ['user:country', [ 272 'user:country_operator' => select::EQUAL_TO, 273 'user:country_value' => 'AU', 274 ], false], 275 'Filter description' => ['user:description', [ 276 'user:description_operator' => text::CONTAINS, 277 'user:description_value' => 'Hello there', 278 ], true], 279 'Filter description (no match)' => ['user:description', [ 280 'user:description_operator' => text::CONTAINS, 281 'user:description_value' => 'Goodbye', 282 ], false], 283 'Filter auth' => ['user:auth', [ 284 'user:auth_operator' => select::EQUAL_TO, 285 'user:auth_value' => 'manual', 286 ], true], 287 'Filter auth (no match)' => ['user:auth', [ 288 'user:auth_operator' => select::EQUAL_TO, 289 'user:auth_value' => 'ldap', 290 ], false], 291 'Filter username' => ['user:username', [ 292 'user:username_operator' => text::IS_EQUAL_TO, 293 'user:username_value' => 'zoe1', 294 ], true], 295 'Filter username (no match)' => ['user:username', [ 296 'user:username_operator' => text::IS_EQUAL_TO, 297 'user:username_value' => 'alfie1', 298 ], false], 299 'Filter idnumber' => ['user:idnumber', [ 300 'user:idnumber_operator' => text::IS_EQUAL_TO, 301 'user:idnumber_value' => 'Z0001', 302 ], true], 303 'Filter idnumber (no match)' => ['user:idnumber', [ 304 'user:idnumber_operator' => text::IS_EQUAL_TO, 305 'user:idnumber_value' => 'A0001', 306 ], false], 307 'Filter institution' => ['user:institution', [ 308 'user:institution_operator' => text::IS_EQUAL_TO, 309 'user:institution_value' => 'Farm', 310 ], true], 311 'Filter institution (no match)' => ['user:institution', [ 312 'user:institution_operator' => text::IS_EQUAL_TO, 313 'user:institution_value' => 'University', 314 ], false], 315 'Filter department' => ['user:department', [ 316 'user:department_operator' => text::IS_EQUAL_TO, 317 'user:department_value' => 'Stable', 318 ], true], 319 'Filter department (no match)' => ['user:department', [ 320 'user:department_operator' => text::IS_EQUAL_TO, 321 'user:department_value' => 'Office', 322 ], false], 323 'Filter moodlenetprofile' => ['user:moodlenetprofile', [ 324 'user:moodlenetprofile_operator' => text::IS_EQUAL_TO, 325 'user:moodlenetprofile_value' => '@zoe1@example.com', 326 ], true], 327 'Filter moodlenetprofile (no match)' => ['user:moodlenetprofile', [ 328 'user:moodlenetprofile_operator' => text::IS_EQUAL_TO, 329 'user:moodlenetprofile_value' => '@alfie1@example.com', 330 ], false], 331 'Filter suspended' => ['user:suspended', [ 332 'user:suspended_operator' => boolean_select::NOT_CHECKED, 333 ], true], 334 'Filter suspended (no match)' => ['user:suspended', [ 335 'user:suspended_operator' => boolean_select::CHECKED, 336 ], false], 337 'Filter confirmed' => ['user:confirmed', [ 338 'user:confirmed_operator' => boolean_select::CHECKED, 339 ], true], 340 'Filter confirmed (no match)' => ['user:confirmed', [ 341 'user:confirmed_operator' => boolean_select::NOT_CHECKED, 342 ], false], 343 'Filter timecreated' => ['user:timecreated', [ 344 'user:timecreated_operator' => date::DATE_RANGE, 345 'user:timecreated_from' => 1622502000, 346 ], true], 347 'Filter timecreated (no match)' => ['user:timecreated', [ 348 'user:timecreated_operator' => date::DATE_RANGE, 349 'user:timecreated_from' => 1619823600, 350 'user:timecreated_to' => 1622502000, 351 ], false], 352 'Filter lastaccess' => ['user:lastaccess', [ 353 'user:lastaccess_operator' => date::DATE_EMPTY, 354 ], true], 355 'Filter lastaccess (no match)' => ['user:lastaccess', [ 356 'user:lastaccess_operator' => date::DATE_RANGE, 357 'user:lastaccess_from' => 1619823600, 358 'user:lastaccess_to' => 1622502000, 359 ], false], 360 361 // Tags. 362 'Filter tag name' => ['tag:name', [ 363 'tag:name_operator' => tags::EQUAL_TO, 364 'tag:name_value' => [-1], 365 ], false], 366 'Filter tag name not empty' => ['tag:name', [ 367 'tag:name_operator' => tags::NOT_EMPTY, 368 ], true], 369 ]; 370 } 371 372 /** 373 * Test datasource filters 374 * 375 * @param string $filtername 376 * @param array $filtervalues 377 * @param bool $expectmatch 378 * 379 * @dataProvider datasource_filters_provider 380 */ 381 public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void { 382 $this->resetAfterTest(); 383 384 $user = $this->getDataGenerator()->create_user([ 385 'username' => 'zoe1', 386 'email' => 'zoe1@example.com', 387 'firstname' => 'Zoe', 388 'middlename' => 'Zebediah', 389 'lastname' => 'Zebra', 390 'firstnamephonetic' => 'Eoz', 391 'lastnamephonetic' => 'Arbez', 392 'alternatename' => 'Zee', 393 'idnumber' => 'Z0001', 394 'institution' => 'Farm', 395 'department' => 'Stable', 396 'phone1' => '111', 397 'phone2' => '222', 398 'address' => 'Big Farm', 399 'city' => 'Barcelona', 400 'country' => 'ES', 401 'description' => 'Hello there', 402 'moodlenetprofile' => '@zoe1@example.com', 403 'interests' => ['Horses'], 404 ]); 405 406 /** @var core_reportbuilder_generator $generator */ 407 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 408 409 // Create report containing single column, and given filter. 410 $report = $generator->create_report(['name' => 'Tasks', 'source' => users::class, 'default' => 0]); 411 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:username']); 412 413 // Add filter, set it's values. 414 $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]); 415 $content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues); 416 417 if ($expectmatch) { 418 $this->assertNotEmpty($content); 419 420 // Merge report usernames into easily traversable array. 421 $usernames = array_merge(...array_map('array_values', $content)); 422 $this->assertContains($user->username, $usernames); 423 } else { 424 $this->assertEmpty($content); 425 } 426 } 427 428 /** 429 * Stress test datasource 430 * 431 * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php 432 */ 433 public function test_stress_datasource(): void { 434 if (!PHPUNIT_LONGTEST) { 435 $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); 436 } 437 438 $this->resetAfterTest(); 439 440 $user = $this->getDataGenerator()->create_user(); 441 442 $this->datasource_stress_test_columns(users::class); 443 $this->datasource_stress_test_columns_aggregation(users::class); 444 $this->datasource_stress_test_conditions(users::class, 'user:username'); 445 } 446 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body