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