Proyectos de Subversion Moodle

Rev

Rev 11 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 11 Rev 1441
Línea 16... Línea 16...
16
 
16
 
Línea 17... Línea 17...
17
namespace core_courseformat;
17
namespace core_courseformat;
18
 
18
 
-
 
19
use course_modinfo;
19
use course_modinfo;
20
use moodle_exception;
Línea 20... Línea 21...
20
use moodle_exception;
21
use ReflectionMethod;
21
use stdClass;
22
use stdClass;
22
 
23
 
Línea 27... Línea 28...
27
 * @category   test
28
 * @category   test
28
 * @copyright  2021 Sara Arjona (sara@moodle.com)
29
 * @copyright  2021 Sara Arjona (sara@moodle.com)
29
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 * @coversDefaultClass \core_courseformat\stateactions
31
 * @coversDefaultClass \core_courseformat\stateactions
31
 */
32
 */
32
class stateactions_test extends \advanced_testcase {
33
final class stateactions_test extends \advanced_testcase {
33
    /**
34
    /**
34
     * Helper method to create an activity into a section and add it to the $sections and $activities arrays.
35
     * Helper method to create an activity into a section and add it to the $sections and $activities arrays.
35
     *
36
     *
36
     * @param int $courseid Course identifier where the activity will be added.
37
     * @param int $courseid Course identifier where the activity will be added.
37
     * @param string $type Activity type ('forum', 'assign', ...).
38
     * @param string $type Activity type ('forum', 'assign', ...).
Línea 43... Línea 44...
43
        int $courseid,
44
        int $courseid,
44
        string $type,
45
        string $type,
45
        int $section,
46
        int $section,
46
        bool $visible = true
47
        bool $visible = true
47
    ): int {
48
    ): int {
48
 
-
 
49
        $activity = $this->getDataGenerator()->create_module(
49
        $activity = $this->getDataGenerator()->create_module(
50
            $type,
50
            $type,
51
            ['course' => $courseid],
51
            ['course' => $courseid],
52
            [
52
            [
53
                'section' => $section,
53
                'section' => $section,
Línea 196... Línea 196...
196
     * @param string $role The role of the user that will execute the method.
196
     * @param string $role The role of the user that will execute the method.
197
     * @param string $method the method to call
197
     * @param string $method the method to call
198
     * @param array $params the ids, targetsection and targetcm to use as params
198
     * @param array $params the ids, targetsection and targetcm to use as params
199
     * @param array $expectedresults List of the course module names expected after calling the method.
199
     * @param array $expectedresults List of the course module names expected after calling the method.
200
     * @param bool $expectedexception If this call will raise an exception.
200
     * @param bool $expectedexception If this call will raise an exception.
201
 
-
 
202
     */
201
     */
203
    public function test_get_state(
202
    public function test_get_state(
204
        string $format,
203
        string $format,
205
        string $role,
204
        string $role,
206
        string $method,
205
        string $method,
207
        array $params,
206
        array $params,
208
        array $expectedresults,
207
        array $expectedresults,
209
        bool $expectedexception = false
208
        bool $expectedexception = false
210
    ): void {
209
    ): void {
211
 
-
 
212
        $this->resetAfterTest();
210
        $this->resetAfterTest();
Línea 213... Línea 211...
213
 
211
 
214
        // Create a course with 3 sections, 1 of them hidden.
212
        // Create a course with 3 sections, 1 of them hidden.
Línea 215... Línea 213...
215
        $course = $this->create_course($format, 3, [2]);
213
        $course = $this->create_course($format, 3, [2]);
Línea 216... Línea 214...
216
 
214
 
217
        $references = $this->course_references($course);
215
        $references = $this->course_references($course);
Línea -... Línea 216...
-
 
216
 
-
 
217
        // Create and enrol user using given role.
-
 
218
        $this->set_test_user_by_role($course, $role);
-
 
219
 
-
 
220
        // Some formats, like social, can create some initial activity.
-
 
221
        $modninfo = course_modinfo::instance($course);
-
 
222
        $cms = $modninfo->get_cms();
-
 
223
        $count = 0;
-
 
224
        foreach ($cms as $cm) {
218
 
225
            $references["initialcm{$count}"] = $cm->id;
219
        // Create and enrol user using given role.
226
            $count++;
220
        $this->set_test_user_by_role($course, $role);
227
        }
221
 
228
 
222
        // Add some activities to the course. One visible and one hidden in both sections 1 and 2.
229
        // Add some activities to the course. One visible and one hidden in both sections 1 and 2.
Línea 266... Línea 273...
266
    /**
273
    /**
267
     * Data provider for data request creation tests.
274
     * Data provider for data request creation tests.
268
     *
275
     *
269
     * @return array the testing scenarios
276
     * @return array the testing scenarios
270
     */
277
     */
271
    public function get_state_provider(): array {
278
    public static function get_state_provider(): array {
272
        return array_merge(
279
        return array_merge(
273
            $this->course_state_provider('weeks'),
280
            static::course_state_provider('weeks'),
274
            $this->course_state_provider('topics'),
281
            static::course_state_provider('topics'),
275
            $this->course_state_provider('social'),
282
            static::course_state_provider('social'),
-
 
283
            static::course_state_provider('singleactivity'),
276
            $this->section_state_provider('weeks', 'admin'),
284
            static::section_state_provider('weeks', 'admin'),
277
            $this->section_state_provider('weeks', 'editingteacher'),
285
            static::section_state_provider('weeks', 'editingteacher'),
278
            $this->section_state_provider('weeks', 'student'),
286
            static::section_state_provider('weeks', 'student'),
279
            $this->section_state_provider('topics', 'admin'),
287
            static::section_state_provider('topics', 'admin'),
280
            $this->section_state_provider('topics', 'editingteacher'),
288
            static::section_state_provider('topics', 'editingteacher'),
281
            $this->section_state_provider('topics', 'student'),
289
            static::section_state_provider('topics', 'student'),
282
            $this->section_state_provider('social', 'admin'),
290
            static::section_state_provider('social', 'admin'),
283
            $this->section_state_provider('social', 'editingteacher'),
291
            static::section_state_provider('social', 'editingteacher'),
284
            $this->section_state_provider('social', 'student'),
292
            static::section_state_provider('social', 'student'),
-
 
293
            static::section_state_provider('singleactivity', 'admin'),
-
 
294
            static::section_state_provider('singleactivity', 'editingteacher'),
-
 
295
            static::section_state_provider('singleactivity', 'student'),
285
            $this->cm_state_provider('weeks', 'admin'),
296
            static::cm_state_provider('weeks', 'admin'),
286
            $this->cm_state_provider('weeks', 'editingteacher'),
297
            static::cm_state_provider('weeks', 'editingteacher'),
287
            $this->cm_state_provider('weeks', 'student'),
298
            static::cm_state_provider('weeks', 'student'),
288
            $this->cm_state_provider('topics', 'admin'),
299
            static::cm_state_provider('topics', 'admin'),
289
            $this->cm_state_provider('topics', 'editingteacher'),
300
            static::cm_state_provider('topics', 'editingteacher'),
290
            $this->cm_state_provider('topics', 'student'),
301
            static::cm_state_provider('topics', 'student'),
291
            $this->cm_state_provider('social', 'admin'),
302
            static::cm_state_provider('social', 'admin'),
292
            $this->cm_state_provider('social', 'editingteacher'),
303
            static::cm_state_provider('social', 'editingteacher'),
293
            $this->cm_state_provider('social', 'student'),
304
            static::cm_state_provider('social', 'student'),
-
 
305
            static::cm_state_provider('singleactivity', 'admin'),
-
 
306
            static::cm_state_provider('singleactivity', 'editingteacher'),
-
 
307
            static::cm_state_provider('singleactivity', 'student'),
294
        );
308
        );
295
    }
309
    }
Línea 296... Línea 310...
296
 
310
 
297
    /**
311
    /**
298
     * Course state data provider.
312
     * Course state data provider.
299
     *
313
     *
300
     * @param string $format the course format
314
     * @param string $format the course format
301
     * @return array the testing scenarios
315
     * @return array the testing scenarios
302
     */
316
     */
303
    public function course_state_provider(string $format): array {
317
    public static function course_state_provider(string $format): array {
-
 
318
        $expectedexception = ($format === 'singleactivity');
-
 
319
 
-
 
320
        $cms = ['cm0', 'cm1', 'cm2', 'cm3'];
-
 
321
        // All sections and cms that the user can access to.
-
 
322
        $usersections = ['section0', 'section1', 'section2', 'section3'];
-
 
323
 
-
 
324
        $studentcms = ['cm0'];
-
 
325
        if ($format === 'social') {
-
 
326
            $cms = ['initialcm0', 'cm0', 'cm1', 'cm2', 'cm3'];
-
 
327
            $studentcms = ['initialcm0', 'cm0'];
-
 
328
            $usersections = ['section0']; // Social format only uses section 0 (for all users).
-
 
329
        }
304
        $expectedexception = ($format === 'social');
330
 
305
        return [
331
        return [
306
            // Tests for course_state.
332
            // Tests for course_state.
307
            "admin $format course_state" => [
333
            "admin $format course_state" => [
308
                'format' => $format,
334
                'format' => $format,
Línea 311... Línea 337...
311
                'params' => [
337
                'params' => [
312
                    'ids' => [], 'targetsectionid' => null, 'targetcmid' => null
338
                    'ids' => [], 'targetsectionid' => null, 'targetcmid' => null
313
                ],
339
                ],
314
                'expectedresults' => [
340
                'expectedresults' => [
315
                    'course' => ['course'],
341
                    'course' => ['course'],
316
                    'section' => ['section0', 'section1', 'section2', 'section3'],
342
                    'section' => array_intersect($usersections, ['section0', 'section1', 'section2', 'section3']),
317
                    'cm' => ['cm0', 'cm1', 'cm2', 'cm3'],
343
                    'cm' => $cms,
318
                ],
344
                ],
319
                'expectedexception' => $expectedexception,
345
                'expectedexception' => $expectedexception,
320
            ],
346
            ],
321
            "editingteacher $format course_state" => [
347
            "editingteacher $format course_state" => [
322
                'format' => $format,
348
                'format' => $format,
Línea 325... Línea 351...
325
                'params' => [
351
                'params' => [
326
                    'ids' => [], 'targetsectionid' => null, 'targetcmid' => null
352
                    'ids' => [], 'targetsectionid' => null, 'targetcmid' => null
327
                ],
353
                ],
328
                'expectedresults' => [
354
                'expectedresults' => [
329
                    'course' => ['course'],
355
                    'course' => ['course'],
330
                    'section' => ['section0', 'section1', 'section2', 'section3'],
356
                    'section' => array_intersect($usersections, ['section0', 'section1', 'section2', 'section3']),
331
                    'cm' => ['cm0', 'cm1', 'cm2', 'cm3'],
357
                    'cm' => $cms,
332
                ],
358
                ],
333
                'expectedexception' => $expectedexception,
359
                'expectedexception' => $expectedexception,
334
            ],
360
            ],
335
            "student $format course_state" => [
361
            "student $format course_state" => [
336
                'format' => $format,
362
                'format' => $format,
Línea 339... Línea 365...
339
                'params' => [
365
                'params' => [
340
                    'ids' => [], 'targetsectionid' => null, 'targetcmid' => null
366
                    'ids' => [], 'targetsectionid' => null, 'targetcmid' => null
341
                ],
367
                ],
342
                'expectedresults' => [
368
                'expectedresults' => [
343
                    'course' => ['course'],
369
                    'course' => ['course'],
344
                    'section' => ['section0', 'section1', 'section3'],
370
                    'section' => array_intersect($usersections, ['section0', 'section1', 'section3']),
345
                    'cm' => ['cm0'],
371
                    'cm' => $studentcms,
346
                ],
372
                ],
347
                'expectedexception' => $expectedexception,
373
                'expectedexception' => $expectedexception,
348
            ],
374
            ],
349
        ];
375
        ];
350
    }
376
    }
Línea 354... Línea 380...
354
     *
380
     *
355
     * @param string $format the course format
381
     * @param string $format the course format
356
     * @param string $role the user role
382
     * @param string $role the user role
357
     * @return array the testing scenarios
383
     * @return array the testing scenarios
358
     */
384
     */
359
    public function section_state_provider(string $format, string $role): array {
385
    public static function section_state_provider(string $format, string $role): array {
360
 
-
 
361
        // Social format will raise an exception and debug messages because it does not
386
        // Social format will raise an exception and debug messages because it does not
362
        // use sections and it does not provide a renderer.
387
        // use sections and it does not provide a renderer.
363
        $expectedexception = ($format === 'social');
388
        $expectedexception = ($format === 'singleactivity');
Línea 364... Línea 389...
364
 
389
 
365
        // All sections and cms that the user can access to.
390
        // All sections and cms that the user can access to.
366
        $usersections = ['section0', 'section1', 'section2', 'section3'];
391
        $usersections = ['section0', 'section1', 'section2', 'section3'];
367
        $usercms = ['cm0', 'cm1', 'cm2', 'cm3'];
392
        $usercms = ['cm0', 'cm1', 'cm2', 'cm3'];
368
        if ($role == 'student') {
393
        if ($role == 'student') {
369
            $usersections = ['section0', 'section1', 'section3'];
394
            $usersections = ['section0', 'section1', 'section3'];
370
            $usercms = ['cm0'];
395
            $usercms = ['cm0'];
-
 
396
        }
-
 
397
        if ($format === 'social') {
-
 
398
            $usercms = ['initialcm0', ...$usercms];
-
 
399
            $usersections = ['section0']; // Social format only uses section 0 (for all users).
Línea 371... Línea 400...
371
        }
400
        }
372
 
401
 
373
        return [
402
        return [
374
            "$role $format section_state no section" => [
403
            "$role $format section_state no section" => [
Línea 389... Línea 418...
389
                    'ids' => ['section0'], 'targetsectionid' => null, 'targetcmid' => null
418
                    'ids' => ['section0'], 'targetsectionid' => null, 'targetcmid' => null
390
                ],
419
                ],
391
                'expectedresults' => [
420
                'expectedresults' => [
392
                    'course' => [],
421
                    'course' => [],
393
                    'section' => array_intersect(['section0'], $usersections),
422
                    'section' => array_intersect(['section0'], $usersections),
394
                    'cm' => [],
423
                    'cm' => ($format == 'social') ? ['initialcm0'] : [],
395
                ],
424
                ],
396
                'expectedexception' => $expectedexception,
425
                'expectedexception' => $expectedexception,
397
            ],
426
            ],
398
            "$role $format section_state visible section" => [
427
            "$role $format section_state visible section" => [
399
                'format' => $format,
428
                'format' => $format,
Línea 483... Línea 512...
483
     *
512
     *
484
     * @param string $format the course format
513
     * @param string $format the course format
485
     * @param string $role the user role
514
     * @param string $role the user role
486
     * @return array the testing scenarios
515
     * @return array the testing scenarios
487
     */
516
     */
488
    public function cm_state_provider(string $format, string $role): array {
517
    public static function cm_state_provider(string $format, string $role): array {
489
 
-
 
490
        // All sections and cms that the user can access to.
518
        // All sections and cms that the user can access to.
491
        $usersections = ['section0', 'section1', 'section2', 'section3'];
519
        $usersections = ['section0', 'section1', 'section2', 'section3'];
492
        $usercms = ['cm0', 'cm1', 'cm2', 'cm3'];
520
        $usercms = ['cm0', 'cm1', 'cm2', 'cm3'];
493
        if ($role == 'student') {
521
        if ($role == 'student') {
494
            $usersections = ['section0', 'section1', 'section3'];
522
            $usersections = ['section0', 'section1', 'section3'];
495
            $usercms = ['cm0'];
523
            $usercms = ['cm0'];
496
        }
524
        }
-
 
525
        if ($format === 'social') {
-
 
526
            $usercms = ['initialcm0', ...$usercms];
-
 
527
            $usersections = ['section0']; // Social format only uses section 0 (for all users).
-
 
528
        }
Línea 497... Línea 529...
497
 
529
 
498
        return [
530
        return [
499
            "$role $format cm_state no cms" => [
531
            "$role $format cm_state no cms" => [
500
                'format' => $format,
532
                'format' => $format,
Línea 558... Línea 590...
558
                'expectedresults' => [
590
                'expectedresults' => [
559
                    'course' => [],
591
                    'course' => [],
560
                    'section' => array_intersect(['section1', 'section2'], $usersections),
592
                    'section' => array_intersect(['section1', 'section2'], $usersections),
561
                    'cm' => array_intersect(['cm0'], $usercms),
593
                    'cm' => array_intersect(['cm0'], $usercms),
562
                ],
594
                ],
563
                'expectedexception' => ($format === 'social'),
595
                'expectedexception' => ($format === 'singleactivity'),
564
            ],
596
            ],
565
            "$role $format cm_state using targetcm" => [
597
            "$role $format cm_state using targetcm" => [
566
                'format' => $format,
598
                'format' => $format,
567
                'role' => $role,
599
                'role' => $role,
568
                'method' => 'cm_state',
600
                'method' => 'cm_state',
Línea 859... Línea 891...
859
    /**
891
    /**
860
     * Data provider for basic role tests.
892
     * Data provider for basic role tests.
861
     *
893
     *
862
     * @return array the testing scenarios
894
     * @return array the testing scenarios
863
     */
895
     */
864
    public function basic_role_provider() {
896
    public static function basic_role_provider(): array {
865
        return [
897
        return [
866
            'editingteacher' => [
898
            'editingteacher' => [
867
                'role' => 'editingteacher',
899
                'role' => 'editingteacher',
868
                'expectedexception' => false,
900
                'expectedexception' => false,
869
            ],
901
            ],
Línea 970... Línea 1002...
970
    /**
1002
    /**
971
     * Duplicate course module data provider.
1003
     * Duplicate course module data provider.
972
     *
1004
     *
973
     * @return array the testing scenarios
1005
     * @return array the testing scenarios
974
     */
1006
     */
975
    public function cm_duplicate_provider(): array {
1007
    public static function cm_duplicate_provider(): array {
976
        return [
1008
        return [
977
            'valid cms without target section' => [
1009
            'valid cms without target section' => [
978
                'targetsection' => '',
1010
                'targetsection' => '',
979
                'validcms' => true,
1011
                'validcms' => true,
980
                'role' => 'admin',
1012
                'role' => 'admin',
Línea 1296... Línea 1328...
1296
    /**
1328
    /**
1297
     * Provider for test_section_move_after.
1329
     * Provider for test_section_move_after.
1298
     *
1330
     *
1299
     * @return array the testing scenarios
1331
     * @return array the testing scenarios
1300
     */
1332
     */
1301
    public function section_move_after_provider(): array {
1333
    public static function section_move_after_provider(): array {
1302
        return [
1334
        return [
1303
            'Move sections down' => [
1335
            'Move sections down' => [
1304
                'sectiontomove' => ['section2', 'section4'],
1336
                'sectiontomove' => ['section2', 'section4'],
1305
                'targetsection' => 'section7',
1337
                'targetsection' => 'section7',
1306
                'finalorder' => [
1338
                'finalorder' => [
Línea 1387... Línea 1419...
1387
            ],
1419
            ],
1388
        ];
1420
        ];
1389
    }
1421
    }
Línea 1390... Línea 1422...
1390
 
1422
 
-
 
1423
    /**
-
 
1424
     * Test course module move and subsection move.
-
 
1425
     *
-
 
1426
     * @covers ::cm_move
-
 
1427
     * @dataProvider cm_move_provider
-
 
1428
     * @param string[] $cmtomove the sections to move
-
 
1429
     * @param string $targetsection
-
 
1430
     * @param string[] $expectedcoursetree expected course tree
-
 
1431
     * @param string|null $expectedexception if it will expect an exception.
-
 
1432
     */
-
 
1433
    public function test_cm_move(
-
 
1434
        array $cmtomove,
-
 
1435
        string $targetsection,
-
 
1436
        array $expectedcoursetree,
-
 
1437
        ?string $expectedexception = null
-
 
1438
    ): void {
-
 
1439
        $this->resetAfterTest();
-
 
1440
        $course = $this->create_course('topics', 4, []);
-
 
1441
 
-
 
1442
        $subsection1 = $this->getDataGenerator()->create_module(
-
 
1443
            'subsection', ['course' => $course, 'section' => 1, 'name' => 'subsection1']
-
 
1444
        );
-
 
1445
        $subsection2 = $this->getDataGenerator()->create_module(
-
 
1446
            'subsection', ['course' => $course, 'section' => 1, 'name' => 'subsection2']
-
 
1447
        );
-
 
1448
        $modinfo = get_fast_modinfo($course);
-
 
1449
        $subsection1info = $modinfo->get_section_info_by_component('mod_subsection', $subsection1->id);
-
 
1450
        $subsection2info = $modinfo->get_section_info_by_component('mod_subsection', $subsection2->id);
-
 
1451
 
-
 
1452
        $references = $this->course_references($course);
-
 
1453
        // Add some activities to the course. One visible and one hidden in both sections 1 and 2.
-
 
1454
        $references["cm0"] = $this->create_activity($course->id, 'assign', 0);
-
 
1455
        $references["cm1"] = $this->create_activity($course->id, 'page', 2);
-
 
1456
        $references["cm2"] = $this->create_activity($course->id, 'forum', $subsection1info->sectionnum);
-
 
1457
        $references["subsection1"] = intval($subsection1->cmid);
-
 
1458
        $references["subsection2"] = intval($subsection2->cmid);
-
 
1459
        $references["subsection1sectionid"] = $subsection1info->id;
-
 
1460
        $references["subsection2sectionid"] = $subsection2info->id;
-
 
1461
        $user = $this->getDataGenerator()->create_user();
-
 
1462
        $this->getDataGenerator()->enrol_user($user->id, $course->id, 'editingteacher');
-
 
1463
        $this->setUser($user);
-
 
1464
 
-
 
1465
        // Initialise stateupdates.
-
 
1466
        $courseformat = course_get_format($course->id);
-
 
1467
        $updates = new stateupdates($courseformat);
-
 
1468
 
-
 
1469
        if ($expectedexception) {
-
 
1470
            $this->expectExceptionMessage($expectedexception);
-
 
1471
        }
-
 
1472
        // Execute the method.
-
 
1473
        $actions = new stateactions();
-
 
1474
        // We do this to make sure we can reference subsection1 in the course tree (and not just section5 as subsection1 is
-
 
1475
        // both a module and a subsection).
-
 
1476
        if (str_starts_with($targetsection, 'subsection')) {
-
 
1477
            $targetsection = $targetsection . 'sectionid';
-
 
1478
        }
-
 
1479
        $actions->cm_move(
-
 
1480
            $updates,
-
 
1481
            $course,
-
 
1482
            $this->translate_references($references, $cmtomove),
-
 
1483
            $references[$targetsection]
-
 
1484
        );
-
 
1485
 
-
 
1486
        $coursetree = $this->get_course_tree($course, $references);
-
 
1487
        $this->assertEquals($expectedcoursetree, $coursetree);
-
 
1488
    }
-
 
1489
 
-
 
1490
    /**
-
 
1491
     * Get Course tree for later comparison.
-
 
1492
     *
-
 
1493
     * @param stdClass $course
-
 
1494
     * @param array $references
-
 
1495
     * @return array
-
 
1496
     */
-
 
1497
    private function get_course_tree(stdClass $course, array $references): array {
-
 
1498
        $coursetree = [];
-
 
1499
        $modinfo = get_fast_modinfo($course); // Get refreshed version.
-
 
1500
 
-
 
1501
        $allsections = $modinfo->get_listed_section_info_all();
-
 
1502
        $cmidstoref = array_flip($references);
-
 
1503
        foreach ($allsections as $sectioninfo) {
-
 
1504
            $sectionkey = 'section' . $sectioninfo->sectionnum;
-
 
1505
            $coursetree[$sectionkey] = [];
-
 
1506
            if (empty(trim($sectioninfo->sequence))) {
-
 
1507
                continue;
-
 
1508
            }
-
 
1509
            $cmids = explode(",", $sectioninfo->sequence);
-
 
1510
            foreach ($cmids as $cmid) {
-
 
1511
                $cm = $modinfo->get_cm($cmid);
-
 
1512
                $delegatedsection = $cm->get_delegated_section_info();
-
 
1513
 
-
 
1514
                // Course modules without a delegated section are included as activities.
-
 
1515
                if (!$delegatedsection) {
-
 
1516
                    $coursetree[$sectionkey][] = $cmidstoref[$cmid];
-
 
1517
                    continue;
-
 
1518
                }
-
 
1519
 
-
 
1520
                // Course modules with a delegated are included as a section, not as an activity.
-
 
1521
                $delegatedsectionkey = $delegatedsection->name; // We gave it a name, so let's use it as key.
-
 
1522
                $coursetree[$sectionkey][$delegatedsectionkey] = [];
-
 
1523
 
-
 
1524
                if (empty(trim($delegatedsection->sequence))) {
-
 
1525
                    continue;
-
 
1526
                }
-
 
1527
                $delegatedcmids = explode(",", $delegatedsection->sequence);
-
 
1528
                foreach ($delegatedcmids as $dcmid) {
-
 
1529
                    $coursetree[$sectionkey][$delegatedsectionkey][] = $cmidstoref[$dcmid];
-
 
1530
                }
-
 
1531
 
-
 
1532
            }
-
 
1533
        }
-
 
1534
        return $coursetree;
-
 
1535
    }
-
 
1536
 
-
 
1537
    /**
-
 
1538
     * Provider for test_section_move.
-
 
1539
     *
-
 
1540
     *
-
 
1541
     * The original coursetree looks like this:
-
 
1542
     * 'coursetree' => [
-
 
1543
     *    'section0' => ['cm0'],
-
 
1544
     *    'section1' => ['subsection1' => ['cm2'],'subsection2' => []],
-
 
1545
     *    'section2' => ['cm1'],
-
 
1546
     *    'section3' => [],
-
 
1547
     *    'section4' => [],
-
 
1548
     * ],
-
 
1549
     *
-
 
1550
     * @return array the testing scenarios
-
 
1551
     */
-
 
1552
    public static function cm_move_provider(): array {
-
 
1553
        return [
-
 
1554
            'Move module into section2' => [
-
 
1555
                'cmtomove' => ['cm0'],
-
 
1556
                'targetsection' => 'section2',
-
 
1557
                'expectedcoursetree' => [
-
 
1558
                    'section0' => [],
-
 
1559
                    'section1' => ['subsection1' => ['cm2'], 'subsection2' => []],
-
 
1560
                    'section2' => ['cm1', 'cm0'],
-
 
1561
                    'section3' => [],
-
 
1562
                    'section4' => [],
-
 
1563
                ],
-
 
1564
            ],
-
 
1565
            'Move subsection into another subsection' => [
-
 
1566
                'cmtomove' => ['subsection1'], // When moving a subsection we actually move the delegated module.
-
 
1567
                'targetsection' => 'subsection2',
-
 
1568
                'expectedcoursetree' => [],
-
 
1569
                'expectedexception' => 'error/subsectionmoveerror',
-
 
1570
            ],
-
 
1571
            'Move module into subsection' => [
-
 
1572
                'cmtomove' => ['cm1'],
-
 
1573
                'targetsection' => 'subsection1',
-
 
1574
                'expectedcoursetree' => [
-
 
1575
                    'section0' => ['cm0'],
-
 
1576
                    'section1' => ['subsection1' => ['cm2', 'cm1'], 'subsection2' => []],
-
 
1577
                    'section2' => [],
-
 
1578
                    'section3' => [],
-
 
1579
                    'section4' => [],
-
 
1580
                ],
-
 
1581
            ],
-
 
1582
        ];
-
 
1583
    }
-
 
1584
 
1391
    /**
1585
    /**
1392
     * Test for section_move_after capability checks.
1586
     * Test for section_move_after capability checks.
1393
     *
1587
     *
1394
     * @covers ::section_move_after
1588
     * @covers ::section_move_after
1395
     * @dataProvider basic_role_provider
1589
     * @dataProvider basic_role_provider
Línea 1417... Línea 1611...
1417
            null,
1611
            null,
1418
            0,
1612
            0,
1419
            'section0'
1613
            'section0'
1420
        );
1614
        );
1421
    }
1615
    }
-
 
1616
 
-
 
1617
    /**
-
 
1618
     * Test that set_cm_indentation on activities with a delegated section.
-
 
1619
     *
-
 
1620
     * @covers ::set_cm_indentation
-
 
1621
     */
-
 
1622
    public function test_set_cm_indentation_delegated_section(): void {
-
 
1623
        global $DB;
-
 
1624
 
-
 
1625
        $this->resetAfterTest();
-
 
1626
        $this->setAdminUser();
-
 
1627
 
-
 
1628
        $course = $this->getDataGenerator()->create_course();
-
 
1629
        $subsection = $this->getDataGenerator()->create_module('subsection', ['course' => $course]);
-
 
1630
        $otheractvity = $this->getDataGenerator()->create_module('forum', ['course' => $course]);
-
 
1631
        $this->setAdminUser();
-
 
1632
 
-
 
1633
        // Initialise stateupdates.
-
 
1634
        $courseformat = course_get_format($course->id);
-
 
1635
 
-
 
1636
        // Execute given method.
-
 
1637
        $updates = new stateupdates($courseformat);
-
 
1638
        $actions = new stateactions();
-
 
1639
        $actions->cm_moveright(
-
 
1640
            $updates,
-
 
1641
            $course,
-
 
1642
            [$subsection->cmid, $otheractvity->cmid],
-
 
1643
        );
-
 
1644
 
-
 
1645
        // Format results in a way we can compare easily.
-
 
1646
        $results = $this->summarize_updates($updates);
-
 
1647
 
-
 
1648
        // The state actions does not use create or remove actions because they are designed
-
 
1649
        // to refresh parts of the state.
-
 
1650
        $this->assertEquals(0, $results['create']['count']);
-
 
1651
        $this->assertEquals(0, $results['remove']['count']);
-
 
1652
 
-
 
1653
        // Mod subsection should be ignored.
-
 
1654
        $this->assertEquals(1, $results['put']['count']);
-
 
1655
 
-
 
1656
        // Validate course, section and cm.
-
 
1657
        $this->assertArrayHasKey($otheractvity->cmid, $results['put']['cm']);
-
 
1658
        $this->assertArrayNotHasKey($subsection->cmid, $results['put']['cm']);
-
 
1659
 
-
 
1660
        // Validate activity indentation.
-
 
1661
        $mondinfo = get_fast_modinfo($course);
-
 
1662
        $this->assertEquals(1, $mondinfo->get_cm($otheractvity->cmid)->indent);
-
 
1663
        $this->assertEquals(1, $DB->get_field('course_modules', 'indent', ['id' => $otheractvity->cmid]));
-
 
1664
        $this->assertEquals(0, $mondinfo->get_cm($subsection->cmid)->indent);
-
 
1665
        $this->assertEquals(0, $DB->get_field('course_modules', 'indent', ['id' => $subsection->cmid]));
-
 
1666
 
-
 
1667
        // Now move left.
-
 
1668
        $updates = new stateupdates($courseformat);
-
 
1669
        $actions->cm_moveleft(
-
 
1670
            $updates,
-
 
1671
            $course,
-
 
1672
            [$subsection->cmid, $otheractvity->cmid],
-
 
1673
        );
-
 
1674
 
-
 
1675
        // Format results in a way we can compare easily.
-
 
1676
        $results = $this->summarize_updates($updates);
-
 
1677
 
-
 
1678
        // The state actions does not use create or remove actions because they are designed
-
 
1679
        // to refresh parts of the state.
-
 
1680
        $this->assertEquals(0, $results['create']['count']);
-
 
1681
        $this->assertEquals(0, $results['remove']['count']);
-
 
1682
 
-
 
1683
        // Mod subsection should be ignored.
-
 
1684
        $this->assertEquals(1, $results['put']['count']);
-
 
1685
 
-
 
1686
        // Validate course, section and cm.
-
 
1687
        $this->assertArrayHasKey($otheractvity->cmid, $results['put']['cm']);
-
 
1688
        $this->assertArrayNotHasKey($subsection->cmid, $results['put']['cm']);
-
 
1689
 
-
 
1690
        // Validate activity indentation.
-
 
1691
        $mondinfo = get_fast_modinfo($course);
-
 
1692
        $this->assertEquals(0, $mondinfo->get_cm($otheractvity->cmid)->indent);
-
 
1693
        $this->assertEquals(0, $DB->get_field('course_modules', 'indent', ['id' => $otheractvity->cmid]));
-
 
1694
        $this->assertEquals(0, $mondinfo->get_cm($subsection->cmid)->indent);
-
 
1695
        $this->assertEquals(0, $DB->get_field('course_modules', 'indent', ['id' => $subsection->cmid]));
-
 
1696
    }
-
 
1697
 
-
 
1698
    /**
-
 
1699
     * Test for filter_cms_with_section_delegate protected method.
-
 
1700
     *
-
 
1701
     * @covers ::filter_cms_with_section_delegate
-
 
1702
     */
-
 
1703
    public function test_filter_cms_with_section_delegate(): void {
-
 
1704
        $this->resetAfterTest();
-
 
1705
        $this->setAdminUser();
-
 
1706
 
-
 
1707
        $course = $this->getDataGenerator()->create_course();
-
 
1708
        $subsection = $this->getDataGenerator()->create_module('subsection', ['course' => $course]);
-
 
1709
        $otheractvity = $this->getDataGenerator()->create_module('forum', ['course' => $course]);
-
 
1710
        $this->setAdminUser();
-
 
1711
 
-
 
1712
        $courseformat = course_get_format($course->id);
-
 
1713
 
-
 
1714
        $modinfo = $courseformat->get_modinfo();
-
 
1715
        $subsectioninfo = $modinfo->get_cm($subsection->cmid);
-
 
1716
        $otheractvityinfo = $modinfo->get_cm($otheractvity->cmid);
-
 
1717
 
-
 
1718
        $actions = new stateactions();
-
 
1719
 
-
 
1720
        $method = new ReflectionMethod($actions, 'filter_cms_with_section_delegate');
-
 
1721
        $result = $method->invoke($actions, [$subsectioninfo, $otheractvityinfo]);
-
 
1722
 
-
 
1723
        $this->assertCount(1, $result);
-
 
1724
        $this->assertArrayHasKey($otheractvity->cmid, $result);
-
 
1725
        $this->assertArrayNotHasKey($subsection->cmid, $result);
-
 
1726
        $this->assertEquals($otheractvityinfo, $result[$otheractvityinfo->id]);
-
 
1727
    }
-
 
1728
 
-
 
1729
    /**
-
 
1730
     * Test for create_module public method.
-
 
1731
     *
-
 
1732
     * @covers ::create_module
-
 
1733
     */
-
 
1734
    public function test_create_module(): void {
-
 
1735
        $this->resetAfterTest();
-
 
1736
 
-
 
1737
        $modname = 'subsection';
-
 
1738
        $manager = \core_plugin_manager::resolve_plugininfo_class('mod');
-
 
1739
        $manager::enable_plugin($modname, 1);
-
 
1740
 
-
 
1741
        // Create a course with 1 section and 1 student.
-
 
1742
        $course = $this->getDataGenerator()->create_course(['numsections' => 1]);
-
 
1743
        $courseformat = course_get_format($course->id);
-
 
1744
        $targetsection = $courseformat->get_modinfo()->get_section_info(1);
-
 
1745
 
-
 
1746
        $this->setAdminUser();
-
 
1747
 
-
 
1748
        // Sanity check.
-
 
1749
        $this->assertEmpty($courseformat->get_modinfo()->get_cms());
-
 
1750
 
-
 
1751
        // Execute given method.
-
 
1752
        $actions = new stateactions();
-
 
1753
        $updates = new stateupdates($courseformat);
-
 
1754
        $actions->create_module($updates, $course, $modname, $targetsection->sectionnum);
-
 
1755
 
-
 
1756
        // Validate cm was created and updates were generated.
-
 
1757
        $results = $this->summarize_updates($updates);
-
 
1758
        $cmupdate = reset($results['put']['cm']);
-
 
1759
        $this->assertCount(1, $courseformat->get_modinfo()->get_cms());
-
 
1760
        $this->assertEquals($modname, $cmupdate->module);
-
 
1761
        $this->assertEquals($targetsection->id, $cmupdate->sectionid);
-
 
1762
        $this->assertEquals(get_string('quickcreatename', 'mod_' . $modname), $cmupdate->name);
-
 
1763
        $this->assertDebuggingCalled();
-
 
1764
    }
-
 
1765
 
-
 
1766
    /**
-
 
1767
     * Test for create_module public method with no capabilities.
-
 
1768
     *
-
 
1769
     * @covers ::create_module
-
 
1770
     */
-
 
1771
    public function test_create_module_no_capabilities(): void {
-
 
1772
        $this->resetAfterTest();
-
 
1773
 
-
 
1774
        $modname = 'subsection';
-
 
1775
 
-
 
1776
        // Create a course with 1 section and 1 student.
-
 
1777
        $course = $this->getDataGenerator()->create_course(['numsections' => 1]);
-
 
1778
        $student = $this->getDataGenerator()->create_user();
-
 
1779
        $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student');
-
 
1780
        $courseformat = course_get_format($course->id);
-
 
1781
        $targetsection = $courseformat->get_modinfo()->get_section_info(1);
-
 
1782
 
-
 
1783
        $this->setAdminUser();
-
 
1784
 
-
 
1785
        // Sanity check.
-
 
1786
        $this->assertEmpty($courseformat->get_modinfo()->get_cms());
-
 
1787
 
-
 
1788
        // Change to a user without permission.
-
 
1789
        $this->setUser($student);
-
 
1790
 
-
 
1791
        // Validate that the method throws an exception.
-
 
1792
        $actions = new stateactions();
-
 
1793
        $updates = new stateupdates($courseformat);
-
 
1794
 
-
 
1795
        // Capturing exceptions on deprecated methods is tricky because expectException is executed
-
 
1796
        // before assertDebuggingCalled. We need to use try catch in a creative way.
-
 
1797
        try {
-
 
1798
            $actions->create_module($updates, $course, $modname, $targetsection->sectionnum);
-
 
1799
        } catch (moodle_exception $exception) {
-
 
1800
            $this->assertDebuggingCalled();
-
 
1801
            $this->expectException(moodle_exception::class);
-
 
1802
            throw $exception;
-
 
1803
        }
-
 
1804
    }
-
 
1805
 
-
 
1806
    /**
-
 
1807
     * Test for create_module public method with targetcmid parameter.
-
 
1808
     *
-
 
1809
     * @covers ::create_module
-
 
1810
     */
-
 
1811
    public function test_create_module_with_targetcmid(): void {
-
 
1812
        $this->resetAfterTest();
-
 
1813
 
-
 
1814
        $modname = 'subsection';
-
 
1815
        $manager = \core_plugin_manager::resolve_plugininfo_class('mod');
-
 
1816
        $manager::enable_plugin($modname, 1);
-
 
1817
 
-
 
1818
        // Create a course with 1 section, 2 modules (forum and page) and 1 student.
-
 
1819
        $course = $this->getDataGenerator()->create_course(['numsections' => 1]);
-
 
1820
        $forum = $this->getDataGenerator()->create_module('forum', ['course' => $course], ['section' => 1]);
-
 
1821
        $page = $this->getDataGenerator()->create_module('page', ['course' => $course], ['section' => 1]);
-
 
1822
        $student = $this->getDataGenerator()->create_user();
-
 
1823
        $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student');
-
 
1824
        $courseformat = course_get_format($course->id);
-
 
1825
        $targetsection = $courseformat->get_modinfo()->get_section_info(1);
-
 
1826
 
-
 
1827
        $this->setAdminUser();
-
 
1828
 
-
 
1829
        // Sanity check.
-
 
1830
        $this->assertCount(2, $courseformat->get_modinfo()->get_cms());
-
 
1831
 
-
 
1832
        // Execute given method.
-
 
1833
        $actions = new stateactions();
-
 
1834
        $updates = new stateupdates($courseformat);
-
 
1835
        $actions->create_module($updates, $course, $modname, $targetsection->sectionnum, $page->cmid);
-
 
1836
 
-
 
1837
        $modinfo = $courseformat->get_modinfo();
-
 
1838
        $cms = $modinfo->get_cms();
-
 
1839
        $results = $this->summarize_updates($updates);
-
 
1840
        $cmupdate = reset($results['put']['cm']);
-
 
1841
 
-
 
1842
        // Validate updates were generated.
-
 
1843
        $this->assertEquals($modname, $cmupdate->module);
-
 
1844
        $this->assertEquals($targetsection->id, $cmupdate->sectionid);
-
 
1845
        $this->assertEquals(get_string('quickcreatename', 'mod_' . $modname), $cmupdate->name);
-
 
1846
 
-
 
1847
        // Validate that the new module was created between both modules.
-
 
1848
        $this->assertCount(3, $cms);
-
 
1849
        $this->assertArrayHasKey($cmupdate->id, $cms);
-
 
1850
        $this->assertEquals(
-
 
1851
            implode(',', [$forum->cmid, $cmupdate->id, $page->cmid]),
-
 
1852
            $modinfo->get_section_info(1)->sequence
-
 
1853
        );
-
 
1854
        $this->assertDebuggingCalled();
-
 
1855
    }
-
 
1856
 
-
 
1857
    /**
-
 
1858
     * Test for new_module public method.
-
 
1859
     *
-
 
1860
     * @covers ::new_module
-
 
1861
     */
-
 
1862
    public function test_new_module(): void {
-
 
1863
        $this->resetAfterTest();
-
 
1864
 
-
 
1865
        $modname = 'subsection';
-
 
1866
 
-
 
1867
        // Create a course with 1 section and 1 student.
-
 
1868
        $course = $this->getDataGenerator()->create_course(['numsections' => 1]);
-
 
1869
        $courseformat = course_get_format($course->id);
-
 
1870
        $targetsection = $courseformat->get_modinfo()->get_section_info(1);
-
 
1871
 
-
 
1872
        $this->setAdminUser();
-
 
1873
 
-
 
1874
        // Sanity check.
-
 
1875
        $this->assertEmpty($courseformat->get_modinfo()->get_cms());
-
 
1876
 
-
 
1877
        // Execute given method.
-
 
1878
        $actions = new stateactions();
-
 
1879
        $updates = new stateupdates($courseformat);
-
 
1880
        $actions->new_module($updates, $course, $modname, $targetsection->id);
-
 
1881
 
-
 
1882
        // Validate cm was created and updates were generated.
-
 
1883
        $results = $this->summarize_updates($updates);
-
 
1884
        $cmupdate = reset($results['put']['cm']);
-
 
1885
        $this->assertCount(1, $courseformat->get_modinfo()->get_cms());
-
 
1886
        $this->assertEquals($modname, $cmupdate->module);
-
 
1887
        $this->assertEquals($targetsection->id, $cmupdate->sectionid);
-
 
1888
        $this->assertEquals(get_string('quickcreatename', 'mod_' . $modname), $cmupdate->name);
-
 
1889
    }
-
 
1890
 
-
 
1891
    /**
-
 
1892
     * Test for new_module public method with no capabilities.
-
 
1893
     *
-
 
1894
     * @covers ::new_module
-
 
1895
     */
-
 
1896
    public function test_new_module_no_capabilities(): void {
-
 
1897
        $this->resetAfterTest();
-
 
1898
 
-
 
1899
        $modname = 'subsection';
-
 
1900
 
-
 
1901
        // Create a course with 1 section and 1 student.
-
 
1902
        $course = $this->getDataGenerator()->create_course(['numsections' => 1]);
-
 
1903
        $student = $this->getDataGenerator()->create_user();
-
 
1904
        $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student');
-
 
1905
        $courseformat = course_get_format($course->id);
-
 
1906
        $targetsection = $courseformat->get_modinfo()->get_section_info(1);
-
 
1907
 
-
 
1908
        $this->setAdminUser();
-
 
1909
 
-
 
1910
        // Sanity check.
-
 
1911
        $this->assertEmpty($courseformat->get_modinfo()->get_cms());
-
 
1912
 
-
 
1913
        // Change to a user without permission.
-
 
1914
        $this->setUser($student);
-
 
1915
 
-
 
1916
        // Validate that the method throws an exception.
-
 
1917
        $actions = new stateactions();
-
 
1918
        $updates = new stateupdates($courseformat);
-
 
1919
 
-
 
1920
        $this->expectException(moodle_exception::class);
-
 
1921
        $actions->new_module($updates, $course, $modname, $targetsection->id);
-
 
1922
    }
-
 
1923
 
-
 
1924
    /**
-
 
1925
     * Test for new_module public method with targetcmid parameter.
-
 
1926
     *
-
 
1927
     * @covers ::new_module
-
 
1928
     */
-
 
1929
    public function test_new_module_with_targetcmid(): void {
-
 
1930
        $this->resetAfterTest();
-
 
1931
 
-
 
1932
        $modname = 'subsection';
-
 
1933
 
-
 
1934
        // Create a course with 1 section, 2 modules (forum and page) and 1 student.
-
 
1935
        $course = $this->getDataGenerator()->create_course(['numsections' => 1]);
-
 
1936
        $forum = $this->getDataGenerator()->create_module('forum', ['course' => $course], ['section' => 1]);
-
 
1937
        $page = $this->getDataGenerator()->create_module('page', ['course' => $course], ['section' => 1]);
-
 
1938
        $student = $this->getDataGenerator()->create_user();
-
 
1939
        $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student');
-
 
1940
        $courseformat = course_get_format($course->id);
-
 
1941
        $targetsection = $courseformat->get_modinfo()->get_section_info(1);
-
 
1942
 
-
 
1943
        $this->setAdminUser();
-
 
1944
 
-
 
1945
        // Sanity check.
-
 
1946
        $this->assertCount(2, $courseformat->get_modinfo()->get_cms());
-
 
1947
 
-
 
1948
        // Execute given method.
-
 
1949
        $actions = new stateactions();
-
 
1950
        $updates = new stateupdates($courseformat);
-
 
1951
        $actions->new_module($updates, $course, $modname, $targetsection->id, $page->cmid);
-
 
1952
 
-
 
1953
        $modinfo = $courseformat->get_modinfo();
-
 
1954
        $cms = $modinfo->get_cms();
-
 
1955
        $results = $this->summarize_updates($updates);
-
 
1956
        $cmupdate = reset($results['put']['cm']);
-
 
1957
 
-
 
1958
        // Validate updates were generated.
-
 
1959
        $this->assertEquals($modname, $cmupdate->module);
-
 
1960
        $this->assertEquals($targetsection->id, $cmupdate->sectionid);
-
 
1961
        $this->assertEquals(get_string('quickcreatename', 'mod_' . $modname), $cmupdate->name);
-
 
1962
 
-
 
1963
        // Validate that the new module was created between both modules.
-
 
1964
        $this->assertCount(3, $cms);
-
 
1965
        $this->assertArrayHasKey($cmupdate->id, $cms);
-
 
1966
        $this->assertEquals(
-
 
1967
            implode(',', [$forum->cmid, $cmupdate->id, $page->cmid]),
-
 
1968
            $modinfo->get_section_info(1)->sequence
-
 
1969
        );
-
 
1970
    }
1422
}
1971
}