Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [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  /**
  18   * A collection of tests for accesslib::has_capability().
  19   *
  20   * @package    core
  21   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  /**
  26   * Unit tests tests for has_capability.
  27   *
  28   * @package    core
  29   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  30   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31   * @covers ::has_capability
  32   */
  33  class accesslib_has_capability_test extends \advanced_testcase {
  34  
  35      /**
  36       * Unit tests to check the operation of locked contexts.
  37       *
  38       * Note: We only check the admin user here.
  39       * If the admin cannot do it, then no-one can.
  40       *
  41       * @dataProvider locked_context_provider
  42       * @param   string[]    $lockedcontexts The list of contexts, by name, to mark as locked
  43       * @param   string[]    $blocked The list of contexts which will be 'blocked' by has_capability
  44       */
  45      public function test_locked_contexts($lockedcontexts, $blocked) {
  46          global $DB;
  47  
  48          $this->resetAfterTest();
  49          set_config('contextlocking', 1);
  50  
  51          $generator = $this->getDataGenerator();
  52          $otheruser = $generator->create_user();
  53  
  54          // / (system)
  55          // /Cat1
  56          // /Cat1/Block
  57          // /Cat1/Course1
  58          // /Cat1/Course1/Block
  59          // /Cat1/Course2
  60          // /Cat1/Course2/Block
  61          // /Cat1/Cat1a
  62          // /Cat1/Cat1a/Block
  63          // /Cat1/Cat1a/Course1
  64          // /Cat1/Cat1a/Course1/Block
  65          // /Cat1/Cat1a/Course2
  66          // /Cat1/Cat1a/Course2/Block
  67          // /Cat1/Cat1b
  68          // /Cat1/Cat1b/Block
  69          // /Cat1/Cat1b/Course1
  70          // /Cat1/Cat1b/Course1/Block
  71          // /Cat1/Cat1b/Course2
  72          // /Cat1/Cat1b/Course2/Block
  73          // /Cat2
  74          // /Cat2/Block
  75          // /Cat2/Course1
  76          // /Cat2/Course1/Block
  77          // /Cat2/Course2
  78          // /Cat2/Course2/Block
  79          // /Cat2/Cat2a
  80          // /Cat2/Cat2a/Block
  81          // /Cat2/Cat2a/Course1
  82          // /Cat2/Cat2a/Course1/Block
  83          // /Cat2/Cat2a/Course2
  84          // /Cat2/Cat2a/Course2/Block
  85          // /Cat2/Cat2b
  86          // /Cat2/Cat2b/Block
  87          // /Cat2/Cat2b/Course1
  88          // /Cat2/Cat2b/Course1/Block
  89          // /Cat2/Cat2b/Course2
  90          // /Cat2/Cat2b/Course2/Block
  91  
  92          $adminuser = \core_user::get_user_by_username('admin');
  93          $contexts = (object) [
  94              'system' => \context_system::instance(),
  95              'adminuser' => \context_user::instance($adminuser->id),
  96          ];
  97  
  98          $cat1 = $generator->create_category();
  99          $cat1a = $generator->create_category(['parent' => $cat1->id]);
 100          $cat1b = $generator->create_category(['parent' => $cat1->id]);
 101  
 102          $contexts->cat1 = \context_coursecat::instance($cat1->id);
 103          $contexts->cat1a = \context_coursecat::instance($cat1a->id);
 104          $contexts->cat1b = \context_coursecat::instance($cat1b->id);
 105  
 106          $cat1course1 = $generator->create_course(['category' => $cat1->id]);
 107          $cat1course2 = $generator->create_course(['category' => $cat1->id]);
 108          $cat1acourse1 = $generator->create_course(['category' => $cat1a->id]);
 109          $cat1acourse2 = $generator->create_course(['category' => $cat1a->id]);
 110          $cat1bcourse1 = $generator->create_course(['category' => $cat1b->id]);
 111          $cat1bcourse2 = $generator->create_course(['category' => $cat1b->id]);
 112  
 113          $contexts->cat1course1 = \context_course::instance($cat1course1->id);
 114          $contexts->cat1acourse1 = \context_course::instance($cat1acourse1->id);
 115          $contexts->cat1bcourse1 = \context_course::instance($cat1bcourse1->id);
 116          $contexts->cat1course2 = \context_course::instance($cat1course2->id);
 117          $contexts->cat1acourse2 = \context_course::instance($cat1acourse2->id);
 118          $contexts->cat1bcourse2 = \context_course::instance($cat1bcourse2->id);
 119  
 120          $cat1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1->id]);
 121          $cat1ablock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1a->id]);
 122          $cat1bblock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1b->id]);
 123          $cat1course1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1course1->id]);
 124          $cat1course2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1course2->id]);
 125          $cat1acourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1acourse1->id]);
 126          $cat1acourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1acourse2->id]);
 127          $cat1bcourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1bcourse1->id]);
 128          $cat1bcourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1bcourse2->id]);
 129  
 130          $contexts->cat1block = \context_block::instance($cat1block->id);
 131          $contexts->cat1ablock = \context_block::instance($cat1ablock->id);
 132          $contexts->cat1bblock = \context_block::instance($cat1bblock->id);
 133          $contexts->cat1course1block = \context_block::instance($cat1course1block->id);
 134          $contexts->cat1course2block = \context_block::instance($cat1course2block->id);
 135          $contexts->cat1acourse1block = \context_block::instance($cat1acourse1block->id);
 136          $contexts->cat1acourse2block = \context_block::instance($cat1acourse2block->id);
 137          $contexts->cat1bcourse1block = \context_block::instance($cat1bcourse1block->id);
 138          $contexts->cat1bcourse2block = \context_block::instance($cat1bcourse2block->id);
 139  
 140          $writecapability = 'moodle/block:edit';
 141          $readcapability = 'moodle/block:view';
 142          $managecapability = 'moodle/site:managecontextlocks';
 143  
 144          $this->setAdminUser();
 145          $totest = (array) $contexts;
 146          foreach ($totest as $context) {
 147              $this->assertTrue(has_capability($writecapability, $context));
 148              $this->assertTrue(has_capability($readcapability, $context));
 149              $this->assertTrue(has_capability($managecapability, $context));
 150          }
 151  
 152          // Lock the specified contexts.
 153          foreach ($lockedcontexts as $contextname => $value) {
 154              $contexts->$contextname->set_locked($value);
 155          }
 156  
 157          // All read capabilities should remain.
 158          foreach ((array) $contexts as $context) {
 159              $this->assertTrue(has_capability($readcapability, $context));
 160              $this->assertTrue(has_capability($managecapability, $context));
 161          }
 162  
 163          // Check writes.
 164          foreach ((array) $contexts as $contextname => $context) {
 165              if (false !== array_search($contextname, $blocked)) {
 166                  $this->assertFalse(has_capability($writecapability, $context));
 167              } else {
 168                  $this->assertTrue(has_capability($writecapability, $context));
 169              }
 170          }
 171  
 172          $this->setUser($otheruser);
 173          // Check writes.
 174          foreach ((array) $contexts as $contextname => $context) {
 175              $this->assertFalse(has_capability($writecapability, $context));
 176          }
 177  
 178          // Disable the contextlocking experimental feature.
 179          set_config('contextlocking', 0);
 180  
 181          $this->setAdminUser();
 182          // All read capabilities should remain.
 183          foreach ((array) $contexts as $context) {
 184              $this->assertTrue(has_capability($readcapability, $context));
 185              $this->assertTrue(has_capability($managecapability, $context));
 186          }
 187  
 188          // All write capabilities should now be present again.
 189          foreach ((array) $contexts as $contextname => $context) {
 190              $this->assertTrue(has_capability($writecapability, $context));
 191          }
 192  
 193          $this->setUser($otheruser);
 194          // Check writes.
 195          foreach ((array) $contexts as $contextname => $context) {
 196              $this->assertFalse(has_capability($writecapability, $context));
 197          }
 198      }
 199  
 200      /**
 201       * Unit tests to check the operation of locked contexts.
 202       *
 203       * Note: We only check the admin user here.
 204       * If the admin cannot do it, then no-one can.
 205       *
 206       * @dataProvider locked_context_provider
 207       * @param   string[]    $lockedcontexts The list of contexts, by name, to mark as locked
 208       * @param   string[]    $blocked The list of contexts which will be 'blocked' by has_capability
 209       */
 210      public function test_locked_contexts_for_admin_with_config($lockedcontexts, $blocked) {
 211          global $DB;
 212  
 213          $this->resetAfterTest();
 214          set_config('contextlocking', 1);
 215          set_config('contextlockappliestoadmin', 0);
 216  
 217          $generator = $this->getDataGenerator();
 218          $otheruser = $generator->create_user();
 219  
 220          // / (system)
 221          // /Cat1
 222          // /Cat1/Block
 223          // /Cat1/Course1
 224          // /Cat1/Course1/Block
 225          // /Cat1/Course2
 226          // /Cat1/Course2/Block
 227          // /Cat1/Cat1a
 228          // /Cat1/Cat1a/Block
 229          // /Cat1/Cat1a/Course1
 230          // /Cat1/Cat1a/Course1/Block
 231          // /Cat1/Cat1a/Course2
 232          // /Cat1/Cat1a/Course2/Block
 233          // /Cat1/Cat1b
 234          // /Cat1/Cat1b/Block
 235          // /Cat1/Cat1b/Course1
 236          // /Cat1/Cat1b/Course1/Block
 237          // /Cat1/Cat1b/Course2
 238          // /Cat1/Cat1b/Course2/Block
 239          // /Cat2
 240          // /Cat2/Block
 241          // /Cat2/Course1
 242          // /Cat2/Course1/Block
 243          // /Cat2/Course2
 244          // /Cat2/Course2/Block
 245          // /Cat2/Cat2a
 246          // /Cat2/Cat2a/Block
 247          // /Cat2/Cat2a/Course1
 248          // /Cat2/Cat2a/Course1/Block
 249          // /Cat2/Cat2a/Course2
 250          // /Cat2/Cat2a/Course2/Block
 251          // /Cat2/Cat2b
 252          // /Cat2/Cat2b/Block
 253          // /Cat2/Cat2b/Course1
 254          // /Cat2/Cat2b/Course1/Block
 255          // /Cat2/Cat2b/Course2
 256          // /Cat2/Cat2b/Course2/Block
 257  
 258          $adminuser = \core_user::get_user_by_username('admin');
 259          $contexts = (object) [
 260              'system' => \context_system::instance(),
 261              'adminuser' => \context_user::instance($adminuser->id),
 262          ];
 263  
 264          $cat1 = $generator->create_category();
 265          $cat1a = $generator->create_category(['parent' => $cat1->id]);
 266          $cat1b = $generator->create_category(['parent' => $cat1->id]);
 267  
 268          $contexts->cat1 = \context_coursecat::instance($cat1->id);
 269          $contexts->cat1a = \context_coursecat::instance($cat1a->id);
 270          $contexts->cat1b = \context_coursecat::instance($cat1b->id);
 271  
 272          $cat1course1 = $generator->create_course(['category' => $cat1->id]);
 273          $cat1course2 = $generator->create_course(['category' => $cat1->id]);
 274          $cat1acourse1 = $generator->create_course(['category' => $cat1a->id]);
 275          $cat1acourse2 = $generator->create_course(['category' => $cat1a->id]);
 276          $cat1bcourse1 = $generator->create_course(['category' => $cat1b->id]);
 277          $cat1bcourse2 = $generator->create_course(['category' => $cat1b->id]);
 278  
 279          $contexts->cat1course1 = \context_course::instance($cat1course1->id);
 280          $contexts->cat1acourse1 = \context_course::instance($cat1acourse1->id);
 281          $contexts->cat1bcourse1 = \context_course::instance($cat1bcourse1->id);
 282          $contexts->cat1course2 = \context_course::instance($cat1course2->id);
 283          $contexts->cat1acourse2 = \context_course::instance($cat1acourse2->id);
 284          $contexts->cat1bcourse2 = \context_course::instance($cat1bcourse2->id);
 285  
 286          $cat1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1->id]);
 287          $cat1ablock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1a->id]);
 288          $cat1bblock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1b->id]);
 289          $cat1course1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1course1->id]);
 290          $cat1course2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1course2->id]);
 291          $cat1acourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1acourse1->id]);
 292          $cat1acourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1acourse2->id]);
 293          $cat1bcourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1bcourse1->id]);
 294          $cat1bcourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1bcourse2->id]);
 295  
 296          $contexts->cat1block = \context_block::instance($cat1block->id);
 297          $contexts->cat1ablock = \context_block::instance($cat1ablock->id);
 298          $contexts->cat1bblock = \context_block::instance($cat1bblock->id);
 299          $contexts->cat1course1block = \context_block::instance($cat1course1block->id);
 300          $contexts->cat1course2block = \context_block::instance($cat1course2block->id);
 301          $contexts->cat1acourse1block = \context_block::instance($cat1acourse1block->id);
 302          $contexts->cat1acourse2block = \context_block::instance($cat1acourse2block->id);
 303          $contexts->cat1bcourse1block = \context_block::instance($cat1bcourse1block->id);
 304          $contexts->cat1bcourse2block = \context_block::instance($cat1bcourse2block->id);
 305  
 306          $writecapability = 'moodle/block:edit';
 307          $readcapability = 'moodle/block:view';
 308          $managecapability = 'moodle/site:managecontextlocks';
 309  
 310          $this->setAdminUser();
 311          $totest = (array) $contexts;
 312          foreach ($totest as $context) {
 313              $this->assertTrue(has_capability($writecapability, $context));
 314              $this->assertTrue(has_capability($readcapability, $context));
 315              $this->assertTrue(has_capability($managecapability, $context));
 316          }
 317  
 318          // Lock the specified contexts.
 319          foreach ($lockedcontexts as $contextname => $value) {
 320              $contexts->$contextname->set_locked($value);
 321          }
 322  
 323          // All read capabilities should remain.
 324          foreach ((array) $contexts as $context) {
 325              $this->assertTrue(has_capability($readcapability, $context));
 326              $this->assertTrue(has_capability($managecapability, $context));
 327          }
 328  
 329          // Check writes.
 330          foreach ((array) $contexts as $contextname => $context) {
 331              $this->assertTrue(has_capability($writecapability, $context));
 332          }
 333  
 334          $this->setUser($otheruser);
 335          // Check writes.
 336          foreach ((array) $contexts as $contextname => $context) {
 337              $this->assertFalse(has_capability($writecapability, $context));
 338          }
 339  
 340          // Disable the contextlocking experimental feature.
 341          set_config('contextlocking', 0);
 342  
 343          $this->setAdminUser();
 344          // All read capabilities should remain.
 345          foreach ((array) $contexts as $context) {
 346              $this->assertTrue(has_capability($readcapability, $context));
 347              $this->assertTrue(has_capability($managecapability, $context));
 348          }
 349  
 350          // All write capabilities should now be present again.
 351          foreach ((array) $contexts as $contextname => $context) {
 352              $this->assertTrue(has_capability($writecapability, $context));
 353          }
 354  
 355          $this->setUser($otheruser);
 356          // Check writes.
 357          foreach ((array) $contexts as $contextname => $context) {
 358              $this->assertFalse(has_capability($writecapability, $context));
 359          }
 360      }
 361  
 362      /**
 363       * Data provider for testing that has_capability() deals with locked contexts.
 364       *
 365       * @return  array
 366       */
 367      public function locked_context_provider() {
 368          return [
 369              'All unlocked' => [
 370                  'locked' => [
 371                  ],
 372                  'blockedwrites' => [
 373                  ],
 374              ],
 375              'User is locked (yes, this is weird)' => [
 376                  'locked' => [
 377                      'adminuser' => true,
 378                  ],
 379                  'blockedwrites' => [
 380                      'adminuser',
 381                  ],
 382              ],
 383              'Cat1/Block locked' => [
 384                  'locked' => [
 385                      'cat1block' => true,
 386                  ],
 387                  'blockedwrites' => [
 388                      'cat1block',
 389                  ],
 390              ],
 391              'Cat1' => [
 392                  'locked' => [
 393                      'cat1' => true,
 394                  ],
 395                  'blockedwrites' => [
 396                      'cat1',
 397                      'cat1block',
 398                      'cat1a',
 399                      'cat1ablock',
 400                      'cat1b',
 401                      'cat1bblock',
 402                      'cat1course1',
 403                      'cat1course1block',
 404                      'cat1course2',
 405                      'cat1course2block',
 406                      'cat1acourse1',
 407                      'cat1acourse1block',
 408                      'cat1acourse2',
 409                      'cat1acourse2block',
 410                      'cat1bcourse1',
 411                      'cat1bcourse1block',
 412                      'cat1bcourse2',
 413                      'cat1bcourse2block',
 414                  ],
 415              ],
 416              'Cat1 locked and a child explicitly unlocked' => [
 417                  'locked' => [
 418                      'cat1' => true,
 419                      'cat1a' => false,
 420                  ],
 421                  'blockedwrites' => [
 422                      'cat1',
 423                      'cat1block',
 424                      'cat1a',
 425                      'cat1ablock',
 426                      'cat1b',
 427                      'cat1bblock',
 428                      'cat1course1',
 429                      'cat1course1block',
 430                      'cat1course2',
 431                      'cat1course2block',
 432                      'cat1acourse1',
 433                      'cat1acourse1block',
 434                      'cat1acourse2',
 435                      'cat1acourse2block',
 436                      'cat1bcourse1',
 437                      'cat1bcourse1block',
 438                      'cat1bcourse2',
 439                      'cat1bcourse2block',
 440                  ],
 441              ],
 442          ];
 443      }
 444  
 445      /**
 446       * Data provider for for has_capability tests when logged in as a different user.
 447       *
 448       * @return  array
 449       */
 450      public function login_as_provider(): array {
 451          return [
 452              [
 453                  'system',
 454                  [
 455                      'cat1course1block' => true,
 456                      'cat1course1' => true,
 457                      'cat1course2block' => true,
 458                      'cat1course2' => true,
 459                      'cat2course1block' => true,
 460                      'cat2course1' => true,
 461                      'cat2course2block' => true,
 462                      'cat2course2' => true,
 463                  ],
 464              ],
 465              [
 466                  'cat1',
 467                  [
 468                      'cat1course1block' => true,
 469                      'cat1course1' => true,
 470                      'cat1course2block' => true,
 471                      'cat1course2' => true,
 472  
 473                      'cat2course1block' => false,
 474                      'cat2course1' => false,
 475                      'cat2course2block' => false,
 476                      'cat2course2' => false,
 477                  ],
 478              ],
 479              [
 480                  'cat1course1',
 481                  [
 482                      'cat1course1block' => true,
 483                      'cat1course1' => true,
 484  
 485                      'cat1course2block' => false,
 486                      'cat1course2' => false,
 487                      'cat2course1block' => false,
 488                      'cat2course1' => false,
 489                      'cat2course2block' => false,
 490                      'cat2course2' => false,
 491                  ],
 492              ],
 493              [
 494                  'cat1course1block',
 495                  [
 496                      'cat1course1block' => true,
 497  
 498                      'cat1course1' => false,
 499                      'cat1course2block' => false,
 500                      'cat1course2' => false,
 501                      'cat2course1block' => false,
 502                      'cat2course1' => false,
 503                      'cat2course2block' => false,
 504                      'cat2course2' => false,
 505                  ],
 506              ],
 507          ];
 508      }
 509  
 510      /**
 511       * Test that the log in as functionality works as expected for an administrator.
 512       *
 513       * An administrator logged in as another user assumes all of their capabilities.
 514       *
 515       * @dataProvider    login_as_provider
 516       * @param   string $loginascontext
 517       * @param   array  $testcontexts
 518       */
 519      public function test_login_as_admin(string $loginascontext, array $testcontexts): void {
 520          $this->resetAfterTest();
 521  
 522          $contexts = $this->get_test_data();
 523  
 524          $this->setAdminUser();
 525          $user = $this->getDataGenerator()->create_user();
 526  
 527          $testcontext = $contexts->$loginascontext;
 528          \core\session\manager::loginas($user->id, $testcontext);
 529  
 530          $capability = 'moodle/block:view';
 531          foreach ($testcontexts as $contextname => $hascapability) {
 532              $this->assertEquals($hascapability, has_capability($capability, $contexts->$contextname));
 533          }
 534      }
 535  
 536      /**
 537       * Test that the log in as functionality works as expected for a regulr user.
 538       *
 539       * @dataProvider    login_as_provider
 540       * @param   string $loginascontext
 541       * @param   array  $testcontexts
 542       */
 543      public function test_login_as_user(string $loginascontext, array $testcontexts): void {
 544          $this->resetAfterTest();
 545  
 546          $contexts = $this->get_test_data();
 547  
 548          $initialuser = $this->getDataGenerator()->create_user();
 549          $user = $this->getDataGenerator()->create_user();
 550          $this->setUser($initialuser);
 551  
 552          $testcontext = $contexts->$loginascontext;
 553          \core\session\manager::loginas($user->id, $testcontext);
 554  
 555          $capability = 'moodle/block:view';
 556          foreach ($testcontexts as $contextname => $hascapability) {
 557              $this->assertEquals($hascapability, has_capability($capability, $contexts->$contextname));
 558          }
 559      }
 560  
 561      /**
 562       * Get the test data contexts.
 563       *
 564       * @return  stdClass
 565       */
 566      protected function get_test_data(): stdclass {
 567          $generator = $this->getDataGenerator();
 568          $otheruser = $generator->create_user();
 569  
 570          // / (system)
 571          // /Cat1
 572          // /Cat1/Block
 573          // /Cat1/Course1
 574          // /Cat1/Course1/Block
 575          // /Cat1/Course2
 576          // /Cat1/Course2/Block
 577          // /Cat1/Cat1a
 578          // /Cat1/Cat1a/Block
 579          // /Cat1/Cat1a/Course1
 580          // /Cat1/Cat1a/Course1/Block
 581          // /Cat1/Cat1a/Course2
 582          // /Cat1/Cat1a/Course2/Block
 583          // /Cat1/Cat1b
 584          // /Cat1/Cat1b/Block
 585          // /Cat1/Cat1b/Course1
 586          // /Cat1/Cat1b/Course1/Block
 587          // /Cat1/Cat1b/Course2
 588          // /Cat1/Cat1b/Course2/Block
 589          // /Cat2
 590          // /Cat2/Block
 591          // /Cat2/Course1
 592          // /Cat2/Course1/Block
 593          // /Cat2/Course2
 594          // /Cat2/Course2/Block
 595          // /Cat2/Cat2a
 596          // /Cat2/Cat2a/Block
 597          // /Cat2/Cat2a/Course1
 598          // /Cat2/Cat2a/Course1/Block
 599          // /Cat2/Cat2a/Course2
 600          // /Cat2/Cat2a/Course2/Block
 601          // /Cat2/Cat2b
 602          // /Cat2/Cat2b/Block
 603          // /Cat2/Cat2b/Course1
 604          // /Cat2/Cat2b/Course1/Block
 605          // /Cat2/Cat2b/Course2
 606          // /Cat2/Cat2b/Course2/Block
 607  
 608          $adminuser = \core_user::get_user_by_username('admin');
 609          $contexts = (object) [
 610              'system' => \context_system::instance(),
 611              'adminuser' => \context_user::instance($adminuser->id),
 612          ];
 613  
 614          $cat1 = $generator->create_category();
 615          $cat1a = $generator->create_category(['parent' => $cat1->id]);
 616          $cat1b = $generator->create_category(['parent' => $cat1->id]);
 617  
 618          $contexts->cat1 = \context_coursecat::instance($cat1->id);
 619          $contexts->cat1a = \context_coursecat::instance($cat1a->id);
 620          $contexts->cat1b = \context_coursecat::instance($cat1b->id);
 621  
 622          $cat1course1 = $generator->create_course(['category' => $cat1->id]);
 623          $cat1course2 = $generator->create_course(['category' => $cat1->id]);
 624          $cat1acourse1 = $generator->create_course(['category' => $cat1a->id]);
 625          $cat1acourse2 = $generator->create_course(['category' => $cat1a->id]);
 626          $cat1bcourse1 = $generator->create_course(['category' => $cat1b->id]);
 627          $cat1bcourse2 = $generator->create_course(['category' => $cat1b->id]);
 628  
 629          $contexts->cat1course1 = \context_course::instance($cat1course1->id);
 630          $contexts->cat1acourse1 = \context_course::instance($cat1acourse1->id);
 631          $contexts->cat1bcourse1 = \context_course::instance($cat1bcourse1->id);
 632          $contexts->cat1course2 = \context_course::instance($cat1course2->id);
 633          $contexts->cat1acourse2 = \context_course::instance($cat1acourse2->id);
 634          $contexts->cat1bcourse2 = \context_course::instance($cat1bcourse2->id);
 635  
 636          $cat1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1->id]);
 637          $cat1ablock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1a->id]);
 638          $cat1bblock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1b->id]);
 639          $cat1course1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1course1->id]);
 640          $cat1course2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1course2->id]);
 641          $cat1acourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1acourse1->id]);
 642          $cat1acourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1acourse2->id]);
 643          $cat1bcourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1bcourse1->id]);
 644          $cat1bcourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat1bcourse2->id]);
 645  
 646          $contexts->cat1block = \context_block::instance($cat1block->id);
 647          $contexts->cat1ablock = \context_block::instance($cat1ablock->id);
 648          $contexts->cat1bblock = \context_block::instance($cat1bblock->id);
 649          $contexts->cat1course1block = \context_block::instance($cat1course1block->id);
 650          $contexts->cat1course2block = \context_block::instance($cat1course2block->id);
 651          $contexts->cat1acourse1block = \context_block::instance($cat1acourse1block->id);
 652          $contexts->cat1acourse2block = \context_block::instance($cat1acourse2block->id);
 653          $contexts->cat1bcourse1block = \context_block::instance($cat1bcourse1block->id);
 654          $contexts->cat1bcourse2block = \context_block::instance($cat1bcourse2block->id);
 655  
 656          $cat2 = $generator->create_category();
 657          $cat2a = $generator->create_category(['parent' => $cat2->id]);
 658          $cat2b = $generator->create_category(['parent' => $cat2->id]);
 659  
 660          $contexts->cat2 = \context_coursecat::instance($cat2->id);
 661          $contexts->cat2a = \context_coursecat::instance($cat2a->id);
 662          $contexts->cat2b = \context_coursecat::instance($cat2b->id);
 663  
 664          $cat2course1 = $generator->create_course(['category' => $cat2->id]);
 665          $cat2course2 = $generator->create_course(['category' => $cat2->id]);
 666          $cat2acourse1 = $generator->create_course(['category' => $cat2a->id]);
 667          $cat2acourse2 = $generator->create_course(['category' => $cat2a->id]);
 668          $cat2bcourse1 = $generator->create_course(['category' => $cat2b->id]);
 669          $cat2bcourse2 = $generator->create_course(['category' => $cat2b->id]);
 670  
 671          $contexts->cat2course1 = \context_course::instance($cat2course1->id);
 672          $contexts->cat2acourse1 = \context_course::instance($cat2acourse1->id);
 673          $contexts->cat2bcourse1 = \context_course::instance($cat2bcourse1->id);
 674          $contexts->cat2course2 = \context_course::instance($cat2course2->id);
 675          $contexts->cat2acourse2 = \context_course::instance($cat2acourse2->id);
 676          $contexts->cat2bcourse2 = \context_course::instance($cat2bcourse2->id);
 677  
 678          $cat2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2->id]);
 679          $cat2ablock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2a->id]);
 680          $cat2bblock = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2b->id]);
 681          $cat2course1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2course1->id]);
 682          $cat2course2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2course2->id]);
 683          $cat2acourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2acourse1->id]);
 684          $cat2acourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2acourse2->id]);
 685          $cat2bcourse1block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2bcourse1->id]);
 686          $cat2bcourse2block = $generator->create_block('online_users', ['parentcontextid' => $contexts->cat2bcourse2->id]);
 687  
 688          $contexts->cat2block = \context_block::instance($cat2block->id);
 689          $contexts->cat2ablock = \context_block::instance($cat2ablock->id);
 690          $contexts->cat2bblock = \context_block::instance($cat2bblock->id);
 691          $contexts->cat2course1block = \context_block::instance($cat2course1block->id);
 692          $contexts->cat2course2block = \context_block::instance($cat2course2block->id);
 693          $contexts->cat2acourse1block = \context_block::instance($cat2acourse1block->id);
 694          $contexts->cat2acourse2block = \context_block::instance($cat2acourse2block->id);
 695          $contexts->cat2bcourse1block = \context_block::instance($cat2bcourse1block->id);
 696          $contexts->cat2bcourse2block = \context_block::instance($cat2bcourse2block->id);
 697  
 698          return $contexts;
 699      }
 700  }