Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
// Note: This namespace is not technically correct, but we have to make it different to the tests for lib/upgradelib.php
18
// and this is more correct than alternatives.
19
namespace core\db;
20
 
21
/**
22
 * Unit tests for the lib/db/upgradelib.php library.
23
 *
24
 * @package   core
25
 * @category  phpunit
26
 * @copyright 2022 Andrew Lyons <andrew@thelyons.family>
27
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28
 */
29
class upgradelib_test extends \advanced_testcase {
30
 
31
    /**
32
     * Shared setup for the testcase.
33
     */
34
    public function setUp(): void {
35
        global $CFG;
36
 
37
        require_once("{$CFG->libdir}/db/upgradelib.php");
38
        require_once("{$CFG->dirroot}/my/lib.php");
39
    }
40
 
41
    /**
42
     * Ensure that the upgrade_block_set_defaultregion function performs as expected.
43
     *
44
     * Only targetted blocks and pages should be affected.
45
     *
46
     * @covers ::upgrade_block_set_defaultregion
47
     */
48
    public function test_upgrade_block_set_defaultregion(): void {
49
        global $DB;
50
 
51
        $this->resetAfterTest();
52
 
53
        // Ensure that only the targetted blocks are affected.
54
 
55
        // Create a my-index entry for the Dashboard.
56
        $dashboardid = $DB->insert_record('my_pages', (object) [
57
            'name' => '__default',
58
            'private' => MY_PAGE_PRIVATE,
59
        ]);
60
 
61
        // Create a page for the my-courses page.
62
        $mycoursesid = $DB->insert_record('my_pages', (object) [
63
            'name' => '__courses',
64
            'private' => MY_PAGE_PRIVATE,
65
        ]);
66
 
67
        $unchanged = [];
68
        $changed = [];
69
 
70
        // Create several blocks of different types.
71
        // These are not linked to the my-index page above, so should not be modified.
72
        $unchanged[] = $this->getDataGenerator()->create_block('online_users', [
73
            'defaultregion' => 'left-side',
74
        ]);
75
        $unchanged[] = $this->getDataGenerator()->create_block('myoverview', [
76
            'defaultregion' => 'left-side',
77
        ]);
78
        $unchanged[] = $this->getDataGenerator()->create_block('calendar_month', [
79
            'defaultregion' => 'left-side',
80
        ]);
81
 
82
        // These are on the my-index above, but are not the block being updated.
83
        $unchanged[] = $this->getDataGenerator()->create_block('online_users', [
84
            'pagetypepattern' => 'my-index',
85
            'subpagepattern' => $dashboardid,
86
            'defaultregion' => 'left-side',
87
        ]);
88
        $unchanged[] = $this->getDataGenerator()->create_block('myoverview', [
89
            'pagetypepattern' => 'my-index',
90
            'subpagepattern' => $dashboardid,
91
            'defaultregion' => 'left-side',
92
        ]);
93
 
94
        // This is on a my-index page, and is the affected block, but is on the mycourses page, not the dashboard.
95
        $unchanged[] = $this->getDataGenerator()->create_block('calendar_month', [
96
            'pagetypepattern' => 'my-index',
97
            'subpagepattern' => $mycoursesid,
98
            'defaultregion' => 'left-side',
99
        ]);
100
 
101
        // This is on the default dashboard, and is the affected block, but not a my-index page.
102
        $unchanged[] = $this->getDataGenerator()->create_block('calendar_month', [
103
            'pagetypepattern' => 'not-my-index',
104
            'subpagepattern' => $dashboardid,
105
            'defaultregion' => 'left-side',
106
        ]);
107
 
108
        // This is the match which should be changed.
109
        $changed[] = $this->getDataGenerator()->create_block('calendar_month', [
110
            'pagetypepattern' => 'my-index',
111
            'subpagepattern' => $dashboardid,
112
            'defaultregion' => 'left-side',
113
        ]);
114
 
115
        // Perform the operation.
116
        // Target all calendar_month blocks matching 'my-index' and update them to the 'content' region where they
117
        // belong to the user dashboard ('pagename' == '__default').
118
        upgrade_block_set_defaultregion('calendar_month', '__default', 'my-index', 'content');
119
 
120
        // Ensure that the relevant blocks remain unchanged.
121
        foreach ($unchanged as $original) {
122
            $block = $DB->get_record('block_instances', ['id' => $original->id]);
123
            $this->assertEquals($original, $block);
124
        }
125
 
126
        // Ensure that only the expected blocks were changed.
127
        foreach ($changed as $original) {
128
            $block = $DB->get_record('block_instances', ['id' => $original->id]);
129
            $this->assertNotEquals($original, $block);
130
 
131
            // Only the defaultregion should be updated to content. No other changes are expected.
132
            $expected = (object) $original;
133
            $expected->defaultregion = 'content';
134
            $this->assertEquals($expected, $block);
135
        }
136
    }
137
 
138
    /**
139
     * Ensure that the upgrade_block_set_defaultregion function performs as expected.
140
     *
141
     * Missing block entries will be created.
142
     *
143
     * @covers ::upgrade_block_set_defaultregion
144
     */
145
    public function test_upgrade_block_set_defaultregion_create_missing(): void {
146
        global $DB;
147
 
148
        $this->resetAfterTest();
149
 
150
        // Ensure that only the targetted blocks are affected.
151
 
152
        $dashboards = [];
153
        $mycourses = [];
154
        // Create dashboard pages for a number of users.
155
        while (count($dashboards) < 10) {
156
            $user = $this->getDataGenerator()->create_user();
157
            $dashboards[] = $DB->insert_record('my_pages', (object) [
158
                'userid' => $user->id,
159
                'name' => '__default',
160
                'private' => MY_PAGE_PRIVATE,
161
            ]);
162
 
163
            $mycourses[] = $DB->insert_record('my_pages', (object) [
164
                'userid' => $user->id,
165
                'name' => '__courses',
166
                'private' => MY_PAGE_PRIVATE,
167
            ]);
168
        }
169
 
170
        // Enusre that there are no blocks initially.
171
        foreach ($dashboards as $dashboardid) {
172
            $this->assertEquals(0, $DB->count_records('block_instances', [
173
                'subpagepattern' => $dashboardid,
174
            ]));
175
        }
176
 
177
        // Perform the operation.
178
        // Target all calendar_month blocks matching 'my-index' and update them to the 'content' region where they
179
        // belong to the user dashboard ('pagename' == '__default').
180
        // Any dashboards which are missing the block will have it created by the operation.
181
        upgrade_block_set_defaultregion('calendar_month', '__default', 'my-index', 'content');
182
 
183
        // Each of the dashboards should now have a block instance of the calendar_month block in the 'content' region
184
        // on 'my-index' only.
185
        foreach ($dashboards as $dashboardid) {
186
            // Only one block should have been created.
187
            $blocks = $DB->get_records('block_instances', [
188
                'subpagepattern' => $dashboardid,
189
            ]);
190
            $this->assertCount(1, $blocks);
191
 
192
            $theblock = reset($blocks);
193
            $this->assertEquals('calendar_month', $theblock->blockname);
194
            $this->assertEquals('content', $theblock->defaultregion);
195
            $this->assertEquals('my-index', $theblock->pagetypepattern);
196
 
197
            // Fetch the user details.
198
            $dashboard = $DB->get_record('my_pages', ['id' => $dashboardid]);
199
            $usercontext = \context_user::instance($dashboard->userid);
200
 
201
            $this->assertEquals($usercontext->id, $theblock->parentcontextid);
202
        }
203
 
204
        // Enusre that there are no blocks on the mycourses page.
205
        foreach ($mycourses as $pageid) {
206
            $this->assertEquals(0, $DB->count_records('block_instances', [
207
                'subpagepattern' => $pageid,
208
            ]));
209
        }
210
    }
211
 
212
    /**
213
     * Ensure that the upgrade_block_delete_instances function performs as expected.
214
     *
215
     * Missing block entries will be created.
216
     *
217
     * @covers ::upgrade_block_delete_instances
218
     */
219
    public function test_upgrade_block_delete_instances(): void {
220
        global $DB;
221
 
222
        $this->resetAfterTest();
223
 
224
        $DB->delete_records('block_instances');
225
 
226
        // Ensure that only the targetted blocks are affected.
227
 
228
        // Get the my-index entry for the Dashboard.
229
        $dashboardid = $DB->get_record('my_pages', [
230
            'userid' => null,
231
            'name' => '__default',
232
            'private' => MY_PAGE_PRIVATE,
233
        ], 'id')->id;
234
 
235
        // Get the page for the my-courses page.
236
        $mycoursesid = $DB->get_record('my_pages', [
237
            'name' => MY_PAGE_COURSES,
238
        ], 'id')->id;
239
 
240
        $dashboards = [];
241
        $unchanged = [];
242
        $unchangedcontexts = [];
243
        $unchangedpreferences = [];
244
        $deleted = [];
245
        $deletedcontexts = [];
246
        $deletedpreferences = [];
247
 
248
        // Create several blocks of different types.
249
        // These are not linked to the my page above, so should not be modified.
250
        $unchanged[] = $this->getDataGenerator()->create_block('online_users', [
251
            'defaultregion' => 'left-side',
252
        ]);
253
        $unchanged[] = $this->getDataGenerator()->create_block('myoverview', [
254
            'defaultregion' => 'left-side',
255
        ]);
256
        $unchanged[] = $this->getDataGenerator()->create_block('calendar_month', [
257
            'defaultregion' => 'left-side',
258
        ]);
259
 
260
        // These are on the my-index above, but are not the block being updated.
261
        $unchanged[] = $this->getDataGenerator()->create_block('online_users', [
262
            'pagetypepattern' => 'my-index',
263
            'subpagepattern' => $dashboardid,
264
            'defaultregion' => 'left-side',
265
        ]);
266
        $unchanged[] = $this->getDataGenerator()->create_block('myoverview', [
267
            'pagetypepattern' => 'my-index',
268
            'subpagepattern' => $dashboardid,
269
            'defaultregion' => 'left-side',
270
        ]);
271
 
272
        // This is on a my-index page, and is the affected block, but is on the mycourses page, not the dashboard.
273
        $unchanged[] = $this->getDataGenerator()->create_block('calendar_month', [
274
            'pagetypepattern' => 'my-index',
275
            'subpagepattern' => $mycoursesid,
276
            'defaultregion' => 'left-side',
277
        ]);
278
 
279
        // This is on the default dashboard, and is the affected block, but not a my-index page.
280
        $unchanged[] = $this->getDataGenerator()->create_block('calendar_month', [
281
            'pagetypepattern' => 'not-my-index',
282
            'subpagepattern' => $dashboardid,
283
            'defaultregion' => 'left-side',
284
        ]);
285
 
286
        // This is the match which should be changed.
287
        $deleted[] = $this->getDataGenerator()->create_block('calendar_month', [
288
            'pagetypepattern' => 'my-index',
289
            'subpagepattern' => $dashboardid,
290
            'defaultregion' => 'left-side',
291
        ]);
292
 
293
        // Create blocks for users with preferences now.
294
        while (count($dashboards) < 10) {
295
            $userunchangedblocks = [];
296
            $userdeletedblocks = [];
297
 
298
            $user = $this->getDataGenerator()->create_user();
299
            $userdashboardid = $DB->insert_record('my_pages', (object) [
300
                'userid' => $user->id,
301
                'name' => '__default',
302
                'private' => MY_PAGE_PRIVATE,
303
            ]);
304
            $dashboards[] = $userdashboardid;
305
 
306
            $usermycoursesid = $DB->insert_record('my_pages', (object) [
307
                'userid' => $user->id,
308
                'name' => '__courses',
309
                'private' => MY_PAGE_PRIVATE,
310
            ]);
311
 
312
            // These are on the my-index above, but are not the block being updated.
313
            $userunchangedblocks[] = $this->getDataGenerator()->create_block('online_users', [
314
                'pagetypepattern' => 'my-index',
315
                'subpagepattern' => $userdashboardid,
316
                'defaultregion' => 'left-side',
317
            ]);
318
            $userunchangedblocks[] = $this->getDataGenerator()->create_block('myoverview', [
319
                'pagetypepattern' => 'my-index',
320
                'subpagepattern' => $userdashboardid,
321
                'defaultregion' => 'left-side',
322
            ]);
323
 
324
            // This is on a my-index page, and is the affected block, but is on the mycourses page, not the dashboard.
325
            $userunchangedblocks[] = $this->getDataGenerator()->create_block('calendar_month', [
326
                'pagetypepattern' => 'my-index',
327
                'subpagepattern' => $usermycoursesid,
328
                'defaultregion' => 'left-side',
329
            ]);
330
 
331
            // This is on the default dashboard, and is the affected block, but not a my-index page.
332
            $userunchangedblocks[] = $this->getDataGenerator()->create_block('calendar_month', [
333
                'pagetypepattern' => 'not-my-index',
334
                'subpagepattern' => $userdashboardid,
335
                'defaultregion' => 'left-side',
336
            ]);
337
 
338
            // This is the match which should be changed.
339
            $userdeletedblocks[] = $this->getDataGenerator()->create_block('calendar_month', [
340
                'pagetypepattern' => 'my-index',
341
                'subpagepattern' => $userdashboardid,
342
                'defaultregion' => 'left-side',
343
            ]);
344
 
345
            $unchanged += $userunchangedblocks;
346
            $deleted += $userdeletedblocks;
347
 
348
            foreach ($userunchangedblocks as $block) {
349
                // Create user preferences for these blocks.
350
                set_user_preference("block{$block->id}hidden", 1, $user);
351
                set_user_preference("docked_block_instance_{$block->id}", 1, $user);
352
                $unchangedpreferences[] = $block->id;
353
            }
354
 
355
            foreach ($userdeletedblocks as $block) {
356
                // Create user preferences for these blocks.
357
                set_user_preference("block{$block->id}hidden", 1, $user);
358
                set_user_preference("docked_block_instance_{$block->id}", 1, $user);
359
                $deletedpreferences[] = $block->id;
360
            }
361
        }
362
 
363
        // Create missing contexts.
364
        \context_helper::create_instances(CONTEXT_BLOCK);
365
 
366
        // Ensure that other related test data is present.
367
        $systemcontext = \context_system::instance();
368
        foreach ($unchanged as $block) {
369
            // Get contexts.
370
            $unchangedcontexts[] = \context_block::instance($block->id);
371
 
372
            // Create a block position.
373
            $DB->insert_record('block_positions', [
374
                'blockinstanceid' => $block->id,
375
                'contextid' => $systemcontext->id,
376
                'pagetype' => 'course-view-topics',
377
                'region' => 'site-post',
378
                'weight' => 1,
379
                'visible' => 1,
380
            ]);
381
        }
382
 
383
        foreach ($deleted as $block) {
384
            // Get contexts.
385
            $deletedcontexts[] = \context_block::instance($block->id);
386
 
387
            // Create a block position.
388
            $DB->insert_record('block_positions', [
389
                'blockinstanceid' => $block->id,
390
                'contextid' => $systemcontext->id,
391
                'pagetype' => 'course-view-topics',
392
                'region' => 'site-post',
393
                'weight' => 1,
394
                'visible' => 1,
395
            ]);
396
        }
397
 
398
        // Perform the operation.
399
        // Target all calendar_month blocks matching 'my-index' and update them to the 'content' region where they
400
        // belong to the user dashboard ('pagename' == '__default').
401
        upgrade_block_delete_instances('calendar_month', '__default', 'my-index');
402
 
403
        // Ensure that the relevant blocks remain unchanged.
404
        foreach ($unchanged as $original) {
405
            $block = $DB->get_record('block_instances', ['id' => $original->id]);
406
            $this->assertEquals($original, $block);
407
 
408
            // Ensure that the block positions remain.
409
            $this->assertEquals(1, $DB->count_records('block_positions', ['blockinstanceid' => $original->id]));
410
        }
411
 
412
        foreach ($unchangedcontexts as $context) {
413
            // Ensure that the context still exists.
414
            $this->assertEquals(1, $DB->count_records('context', ['id' => $context->id]));
415
        }
416
 
417
        foreach ($unchangedpreferences as $blockid) {
418
            // Ensure that the context still exists.
419
            $this->assertEquals(1, $DB->count_records('user_preferences', ['name' => "block{$blockid}hidden"]));
420
            $this->assertEquals(1, $DB->count_records('user_preferences', [
421
                'name' => "docked_block_instance_{$blockid}",
422
            ]));
423
        }
424
 
425
        // Ensure that only the expected blocks were changed.
426
        foreach ($deleted as $original) {
427
            $this->assertCount(0, $DB->get_records('block_instances', ['id' => $original->id]));
428
 
429
            // Ensure that the block positions was removed.
430
            $this->assertEquals(0, $DB->count_records('block_positions', ['blockinstanceid' => $original->id]));
431
        }
432
 
433
        foreach ($deletedcontexts as $context) {
434
            // Ensure that the context still exists.
435
            $this->assertEquals(0, $DB->count_records('context', ['id' => $context->id]));
436
        }
437
 
438
        foreach ($deletedpreferences as $blockid) {
439
            // Ensure that the context still exists.
440
            $this->assertEquals(0, $DB->count_records('user_preferences', ['name' => "block{$blockid}hidden"]));
441
            $this->assertEquals(0, $DB->count_records('user_preferences', [
442
                'name' => "docked_block_instance_{$blockid}",
443
            ]));
444
        }
445
    }
446
 
447
    /**
448
     * Ensrue that the upgrade_block_set_my_user_parent_context function performs as expected.
449
     *
450
     * @covers ::upgrade_block_set_my_user_parent_context
451
     */
452
    public function test_upgrade_block_set_my_user_parent_context(): void {
453
        global $DB;
454
 
455
        $this->resetAfterTest();
456
        $this->preventResetByRollback();
457
 
458
        $systemcontext = \context_system::instance();
459
 
460
        $dashboards = [];
461
        $otherblocknames = [
462
            'online_users',
463
            'myoverview',
464
            'calendar_month',
465
        ];
466
        $affectedblockname = 'timeline';
467
 
468
        // Create dashboard pages for a number of users.
469
        while (count($dashboards) < 10) {
470
            $user = $this->getDataGenerator()->create_user();
471
            $dashboard = $DB->insert_record('my_pages', (object) [
472
                'userid' => $user->id,
473
                'name' => '__default',
474
                'private' => MY_PAGE_PRIVATE,
475
            ]);
476
            $dashboards[] = $dashboard;
477
 
478
            $mycourse = $DB->insert_record('my_pages', (object) [
479
                'userid' => $user->id,
480
                'name' => '__courses',
481
                'private' => MY_PAGE_PRIVATE,
482
            ]);
483
 
484
            // These are on the my-index above, but are not the block being updated.
485
            foreach ($otherblocknames as $blockname) {
486
                $unchanged[] = $this->getDataGenerator()->create_block($blockname, [
487
                    'parentcontextid' => $systemcontext->id,
488
                    'pagetypepattern' => 'my-index',
489
                    'subpagepattern' => $dashboard,
490
                ]);
491
            }
492
 
493
            // This is on a my-index page, and is the affected block, but is on the mycourses page, not the dashboard.
494
            $unchanged[] = $this->getDataGenerator()->create_block($affectedblockname, [
495
                'parentcontextid' => $systemcontext->id,
496
                'pagetypepattern' => 'my-index',
497
                'subpagepattern' => $mycourse,
498
            ]);
499
 
500
            // This is on the default dashboard, and is the affected block, but not a my-index page.
501
            $unchanged[] = $this->getDataGenerator()->create_block($affectedblockname, [
502
                'parentcontextid' => $systemcontext->id,
503
                'pagetypepattern' => 'not-my-index',
504
                'subpagepattern' => $dashboard,
505
            ]);
506
 
507
            // This is the match which should be changed.
508
            $changed[] = $this->getDataGenerator()->create_block($affectedblockname, [
509
                'parentcontextid' => $systemcontext->id,
510
                'pagetypepattern' => 'my-index',
511
                'subpagepattern' => $dashboard,
512
            ]);
513
        }
514
 
515
        // Perform the operation.
516
        // Target all affected blocks matching 'my-index' and correct the context to the relevant user's contexct.
517
        // Only the '__default' dashboard on the 'my-index' my_page should be affected.
518
        upgrade_block_set_my_user_parent_context($affectedblockname, '__default', 'my-index');
519
 
520
        // Ensure that the relevant blocks remain unchanged.
521
        foreach ($unchanged as $original) {
522
            $block = $DB->get_record('block_instances', ['id' => $original->id]);
523
            $this->assertEquals($original, $block);
524
        }
525
 
526
        // Ensure that only the expected blocks were changed.
527
        foreach ($changed as $original) {
528
            $block = $DB->get_record('block_instances', ['id' => $original->id]);
529
            $this->assertNotEquals($original, $block);
530
 
531
            // Fetch the my page and user details.
532
            $dashboard = $DB->get_record('my_pages', ['id' => $original->subpagepattern]);
533
            $usercontext = \context_user::instance($dashboard->userid);
534
 
535
            // Only the contextid should be updated to the relevant user's context.
536
            // No other changes are expected.
537
            $expected = (object) $original;
538
            $expected->parentcontextid = $usercontext->id;
539
            $this->assertEquals($expected, $block);
540
        }
541
    }
542
}