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