Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
namespace core_course\backup;
18
 
19
use backup;
20
use backup_controller;
21
use restore_controller;
22
use restore_dbops;
23
 
24
defined('MOODLE_INTERNAL') || die();
25
global $CFG;
26
 
27
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
28
require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
29
require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest.php');
30
 
31
/**
32
 * Course restore testcase.
33
 *
34
 * @package    core_course
35
 * @copyright  2016 Frédéric Massart - FMCorz.net
36
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 */
38
class restore_test extends \advanced_testcase {
39
 
40
    /**
41
     * Backup a course and return its backup ID.
42
     *
43
     * @param int $courseid The course ID.
44
     * @param int $userid The user doing the backup.
45
     * @return string
46
     */
47
    protected function backup_course($courseid, $userid = 2) {
48
        $backuptempdir = make_backup_temp_directory('');
49
        $packer = get_file_packer('application/vnd.moodle.backup');
50
 
51
        $bc = new backup_controller(backup::TYPE_1COURSE, $courseid, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO,
52
            backup::MODE_GENERAL, $userid);
53
        $bc->execute_plan();
54
 
55
        $results = $bc->get_results();
56
        $results['backup_destination']->extract_to_pathname($packer, "$backuptempdir/core_course_testcase");
57
 
58
        $bc->destroy();
59
        unset($bc);
60
        return 'core_course_testcase';
61
    }
62
 
63
    /**
64
     * Create a role with capabilities and permissions.
65
     *
66
     * @param string|array $caps Capability names.
67
     * @param int $perm Constant CAP_* to apply to the capabilities.
68
     * @return int The new role ID.
69
     */
70
    protected function create_role_with_caps($caps, $perm) {
71
        $caps = (array) $caps;
72
        $dg = $this->getDataGenerator();
73
        $roleid = $dg->create_role();
74
        foreach ($caps as $cap) {
75
            assign_capability($cap, $perm, $roleid, \context_system::instance()->id, true);
76
        }
77
        accesslib_clear_all_caches_for_unit_testing();
78
        return $roleid;
79
    }
80
 
81
    /**
82
     * Restore a course.
83
     *
84
     * @param int $backupid The backup ID.
85
     * @param int $courseid The course ID to restore in, or 0.
86
     * @param int $userid The ID of the user performing the restore.
87
     * @return stdClass The updated course object.
88
     */
89
    protected function restore_course($backupid, $courseid, $userid) {
90
        global $DB;
91
 
92
        $target = backup::TARGET_CURRENT_ADDING;
93
        if (!$courseid) {
94
            $target = backup::TARGET_NEW_COURSE;
95
            $categoryid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
96
            $courseid = restore_dbops::create_new_course('Tmp', 'tmp', $categoryid);
97
        }
98
 
99
        $rc = new restore_controller($backupid, $courseid, backup::INTERACTIVE_NO, backup::MODE_GENERAL, $userid, $target);
100
        $target == backup::TARGET_NEW_COURSE ?: $rc->get_plan()->get_setting('overwrite_conf')->set_value(true);
101
        $this->assertTrue($rc->execute_precheck());
102
        $rc->execute_plan();
103
 
104
        $course = $DB->get_record('course', array('id' => $rc->get_courseid()));
105
 
106
        $rc->destroy();
107
        unset($rc);
108
        return $course;
109
    }
110
 
111
    /**
112
     * Restore a course to an existing course.
113
     *
114
     * @param int $backupid The backup ID.
115
     * @param int $courseid The course ID to restore in.
116
     * @param int $userid The ID of the user performing the restore.
117
     * @return stdClass The updated course object.
118
     */
119
    protected function restore_to_existing_course($backupid, $courseid, $userid = 2) {
120
        return $this->restore_course($backupid, $courseid, $userid);
121
    }
122
 
123
    /**
124
     * Restore a course to a new course.
125
     *
126
     * @param int $backupid The backup ID.
127
     * @param int $userid The ID of the user performing the restore.
128
     * @return stdClass The new course object.
129
     */
130
    protected function restore_to_new_course($backupid, $userid = 2) {
131
        return $this->restore_course($backupid, 0, $userid);
132
    }
133
 
134
    /**
135
     * Restore a course.
136
     *
137
     * @param int $backupid The backup ID.
138
     * @param int $courseid The course ID to restore in, or 0.
139
     * @param int $userid The ID of the user performing the restore.
140
     * @param int $target THe target of the restore.
141
     *
142
     * @return stdClass The updated course object.
143
     */
144
    protected function async_restore_course($backupid, $courseid, $userid, $target) {
145
        global $DB;
146
 
147
        if (!$courseid) {
148
            $target = backup::TARGET_NEW_COURSE;
149
            $categoryid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
150
            $courseid = restore_dbops::create_new_course('Tmp', 'tmp', $categoryid);
151
        }
152
 
153
        $rc = new restore_controller($backupid, $courseid, backup::INTERACTIVE_NO, backup::MODE_ASYNC, $userid, $target);
154
        $target == backup::TARGET_NEW_COURSE ?: $rc->get_plan()->get_setting('overwrite_conf')->set_value(true);
155
        $this->assertTrue($rc->execute_precheck());
156
 
157
        $restoreid = $rc->get_restoreid();
158
        $rc->destroy();
159
 
160
        // Create the adhoc task.
161
        $asynctask = new \core\task\asynchronous_restore_task();
162
        $asynctask->set_custom_data(array('backupid' => $restoreid));
163
        \core\task\manager::queue_adhoc_task($asynctask);
164
 
165
        // We are expecting trace output during this test.
166
        $this->expectOutputRegex("/$restoreid/");
167
 
168
        // Execute adhoc task.
169
        $now = time();
170
        $task = \core\task\manager::get_next_adhoc_task($now);
171
        $this->assertInstanceOf('\\core\\task\\asynchronous_restore_task', $task);
172
        $task->execute();
173
        \core\task\manager::adhoc_task_complete($task);
174
 
175
        $course = $DB->get_record('course', array('id' => $rc->get_courseid()));
176
 
177
        return $course;
178
    }
179
 
180
    /**
181
     * Restore a course to an existing course.
182
     *
183
     * @param int $backupid The backup ID.
184
     * @param int $courseid The course ID to restore in.
185
     * @param int $userid The ID of the user performing the restore.
186
     * @param int $target The type of restore we are performing.
187
     * @return stdClass The updated course object.
188
     */
189
    protected function async_restore_to_existing_course($backupid, $courseid,
190
        $userid = 2, $target = backup::TARGET_CURRENT_ADDING) {
191
        return $this->async_restore_course($backupid, $courseid, $userid, $target);
192
    }
193
 
194
    /**
195
     * Restore a course to a new course.
196
     *
197
     * @param int $backupid The backup ID.
198
     * @param int $userid The ID of the user performing the restore.
199
     * @return stdClass The new course object.
200
     */
201
    protected function async_restore_to_new_course($backupid, $userid = 2) {
202
        return $this->async_restore_course($backupid, 0, $userid, 0);
203
    }
204
 
11 efrain 205
    public function test_async_restore_existing_idnumber_in_new_course(): void {
1 efrain 206
        $this->resetAfterTest();
207
 
208
        $dg = $this->getDataGenerator();
209
        $c1 = $dg->create_course(['idnumber' => 'ABC']);
210
        $backupid = $this->backup_course($c1->id);
211
        $c2 = $this->async_restore_to_new_course($backupid);
212
 
213
        // The ID number is set empty.
214
        $this->assertEquals('', $c2->idnumber);
215
    }
216
 
11 efrain 217
    public function test_async_restore_course_info_in_existing_course(): void {
1 efrain 218
        global $DB;
219
        $this->resetAfterTest();
220
        $dg = $this->getDataGenerator();
221
 
222
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_shortname'));
223
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_fullname'));
224
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_startdate'));
225
 
226
        $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016.
227
 
228
        // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date.
229
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE,
230
            'startdate' => $startdate]);
231
        $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]);
232
        $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN,
233
            'startdate' => $startdate + 2 * WEEKSECS]);
234
        $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]);
235
        $backupid = $this->backup_course($c1->id);
236
 
237
        // The information is restored but adapted because names are already taken.
238
        $c2 = $this->async_restore_to_existing_course($backupid, $c2->id);
239
        $this->assertEquals('SN_1', $c2->shortname);
240
        $this->assertEquals('FN copy 1', $c2->fullname);
241
        $this->assertEquals('DESC', $c2->summary);
242
        $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat);
243
        $this->assertEquals($startdate, $c2->startdate);
244
 
245
        // Now course c2 has two chats - one ('Second') was already there and one ('First') was restored from the backup.
246
        // Their dates are exactly the same as they were in the original modules.
247
        $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]);
248
        $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]);
249
        $this->assertEquals($chat1->chattime, $restoredchat1->chattime);
250
        $this->assertEquals($chat2->chattime, $restoredchat2->chattime);
251
    }
252
 
11 efrain 253
    public function test_async_restore_course_info_in_existing_course_delete_first(): void {
1 efrain 254
        global $DB;
255
        $this->resetAfterTest();
256
        $dg = $this->getDataGenerator();
257
 
258
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_shortname'));
259
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_fullname'));
260
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_startdate'));
261
 
262
        $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016.
263
 
264
        // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date.
265
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE,
266
            'startdate' => $startdate]);
267
        $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]);
268
        $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN,
269
            'startdate' => $startdate + 2 * WEEKSECS]);
270
        $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]);
271
        $backupid = $this->backup_course($c1->id);
272
 
273
        // The information is restored and the existing course settings is modified.
274
        $c2 = $this->async_restore_to_existing_course($backupid, $c2->id, 2, backup::TARGET_CURRENT_DELETING);
275
        $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat);
276
 
277
        // Now course2 should have a new forum with the original forum deleted.
278
        $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]);
279
        $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]);
280
        $this->assertEquals($chat1->chattime, $restoredchat1->chattime);
281
        $this->assertEmpty($restoredchat2);
282
    }
283
 
11 efrain 284
    public function test_restore_existing_idnumber_in_new_course(): void {
1 efrain 285
        $this->resetAfterTest();
286
 
287
        $dg = $this->getDataGenerator();
288
        $c1 = $dg->create_course(['idnumber' => 'ABC']);
289
        $backupid = $this->backup_course($c1->id);
290
        $c2 = $this->restore_to_new_course($backupid);
291
 
292
        // The ID number is set empty.
293
        $this->assertEquals('', $c2->idnumber);
294
    }
295
 
11 efrain 296
    public function test_restore_non_existing_idnumber_in_new_course(): void {
1 efrain 297
        global $DB;
298
        $this->resetAfterTest();
299
 
300
        $dg = $this->getDataGenerator();
301
        $c1 = $dg->create_course(['idnumber' => 'ABC']);
302
        $backupid = $this->backup_course($c1->id);
303
 
304
        $c1->idnumber = 'BCD';
305
        $DB->update_record('course', $c1);
306
 
307
        // The ID number changed.
308
        $c2 = $this->restore_to_new_course($backupid);
309
        $this->assertEquals('ABC', $c2->idnumber);
310
    }
311
 
11 efrain 312
    public function test_restore_existing_idnumber_in_existing_course(): void {
1 efrain 313
        global $DB;
314
        $this->resetAfterTest();
315
 
316
        $dg = $this->getDataGenerator();
317
        $c1 = $dg->create_course(['idnumber' => 'ABC']);
318
        $c2 = $dg->create_course(['idnumber' => 'DEF']);
319
        $backupid = $this->backup_course($c1->id);
320
 
321
        // The ID number does not change.
322
        $c2 = $this->restore_to_existing_course($backupid, $c2->id);
323
        $this->assertEquals('DEF', $c2->idnumber);
324
 
325
        $c1 = $DB->get_record('course', array('id' => $c1->id));
326
        $this->assertEquals('ABC', $c1->idnumber);
327
    }
328
 
11 efrain 329
    public function test_restore_non_existing_idnumber_in_existing_course(): void {
1 efrain 330
        global $DB;
331
        $this->resetAfterTest();
332
 
333
        $dg = $this->getDataGenerator();
334
        $c1 = $dg->create_course(['idnumber' => 'ABC']);
335
        $c2 = $dg->create_course(['idnumber' => 'DEF']);
336
        $backupid = $this->backup_course($c1->id);
337
 
338
        $c1->idnumber = 'XXX';
339
        $DB->update_record('course', $c1);
340
 
341
        // The ID number has changed.
342
        $c2 = $this->restore_to_existing_course($backupid, $c2->id);
343
        $this->assertEquals('ABC', $c2->idnumber);
344
    }
345
 
11 efrain 346
    public function test_restore_idnumber_in_existing_course_without_permissions(): void {
1 efrain 347
        global $DB;
348
        $this->resetAfterTest();
349
        $dg = $this->getDataGenerator();
350
        $u1 = $dg->create_user();
351
 
352
        $managers = get_archetype_roles('manager');
353
        $manager = array_shift($managers);
354
        $roleid = $this->create_role_with_caps('moodle/course:changeidnumber', CAP_PROHIBIT);
355
        $dg->role_assign($manager->id, $u1->id);
356
        $dg->role_assign($roleid, $u1->id);
357
 
358
        $c1 = $dg->create_course(['idnumber' => 'ABC']);
359
        $c2 = $dg->create_course(['idnumber' => 'DEF']);
360
        $backupid = $this->backup_course($c1->id);
361
 
362
        $c1->idnumber = 'XXX';
363
        $DB->update_record('course', $c1);
364
 
365
        // The ID number does not change.
366
        $c2 = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
367
        $this->assertEquals('DEF', $c2->idnumber);
368
    }
369
 
11 efrain 370
    public function test_restore_course_info_in_new_course(): void {
1 efrain 371
        global $DB;
372
        $this->resetAfterTest();
373
        $dg = $this->getDataGenerator();
374
 
375
        $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016.
376
 
377
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'startdate' => $startdate,
378
            'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
379
        $backupid = $this->backup_course($c1->id);
380
 
381
        // The information is restored but adapted because names are already taken.
382
        $c2 = $this->restore_to_new_course($backupid);
383
        $this->assertEquals('SN_1', $c2->shortname);
384
        $this->assertEquals('FN copy 1', $c2->fullname);
385
        $this->assertEquals('DESC', $c2->summary);
386
        $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat);
387
        $this->assertEquals($startdate, $c2->startdate);
388
    }
389
 
11 efrain 390
    public function test_restore_course_with_users(): void {
1 efrain 391
        global $DB;
392
        $this->resetAfterTest();
393
        $this->setAdminUser();
394
        $dg = $this->getDataGenerator();
395
 
396
        // Create a user and a course, enrol user in the course. Backup this course.
397
        $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016.
398
        $u1 = $dg->create_user(['firstname' => 'Olivia']);
399
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'startdate' => $startdate,
400
            'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
401
        $dg->enrol_user($u1->id, $c1->id, 'student');
402
        $backupid = $this->backup_course($c1->id);
403
 
404
        // Delete the course and the user completely.
405
        delete_course($c1, false);
406
        delete_user($u1);
407
        $DB->delete_records('user', ['id' => $u1->id]);
408
 
409
        // Now restore this course, the user will be created and event user_created event will be triggered.
410
        $sink = $this->redirectEvents();
411
        $c2 = $this->restore_to_new_course($backupid);
412
        $events = $sink->get_events();
413
        $sink->close();
414
 
415
        $user = $DB->get_record('user', ['firstname' => 'Olivia'], '*', MUST_EXIST);
416
        $events = array_values(array_filter($events, function(\core\event\base $event) {
417
            return is_a($event, \core\event\user_created::class);
418
        }));
419
        $this->assertEquals(1, count($events));
420
        $this->assertEquals($user->id, $events[0]->relateduserid);
421
        $this->assertEquals($c2->id, $events[0]->other['courseid']);
422
        $this->assertStringContainsString("during restore of the course with id '{$c2->id}'",
423
            $events[0]->get_description());
424
    }
425
 
11 efrain 426
    public function test_restore_course_info_in_existing_course(): void {
1 efrain 427
        global $DB;
428
        $this->resetAfterTest();
429
        $dg = $this->getDataGenerator();
430
 
431
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_shortname'));
432
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_fullname'));
433
        $this->assertEquals(1, get_config('restore', 'restore_merge_course_startdate'));
434
 
435
        $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016.
436
 
437
        // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date.
438
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE,
439
            'startdate' => $startdate]);
440
        $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]);
441
        $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN,
442
            'startdate' => $startdate + 2 * WEEKSECS]);
443
        $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]);
444
        $backupid = $this->backup_course($c1->id);
445
 
446
        // The information is restored but adapted because names are already taken.
447
        $c2 = $this->restore_to_existing_course($backupid, $c2->id);
448
        $this->assertEquals('SN_1', $c2->shortname);
449
        $this->assertEquals('FN copy 1', $c2->fullname);
450
        $this->assertEquals('DESC', $c2->summary);
451
        $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat);
452
        $this->assertEquals($startdate, $c2->startdate);
453
 
454
        // Now course c2 has two chats - one ('Second') was already there and one ('First') was restored from the backup.
455
        // Their dates are exactly the same as they were in the original modules.
456
        $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]);
457
        $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]);
458
        $this->assertEquals($chat1->chattime, $restoredchat1->chattime);
459
        $this->assertEquals($chat2->chattime, $restoredchat2->chattime);
460
    }
461
 
11 efrain 462
    public function test_restore_course_shortname_in_existing_course_without_permissions(): void {
1 efrain 463
        global $DB;
464
        $this->resetAfterTest();
465
        $dg = $this->getDataGenerator();
466
        $u1 = $dg->create_user();
467
 
468
        $managers = get_archetype_roles('manager');
469
        $manager = array_shift($managers);
470
        $roleid = $this->create_role_with_caps('moodle/course:changeshortname', CAP_PROHIBIT);
471
        $dg->role_assign($manager->id, $u1->id);
472
        $dg->role_assign($roleid, $u1->id);
473
 
474
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
475
        $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]);
476
 
477
        // The shortname does not change.
478
        $backupid = $this->backup_course($c1->id);
479
        $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
480
        $this->assertEquals($c2->shortname, $restored->shortname);
481
        $this->assertEquals('FN copy 1', $restored->fullname);
482
        $this->assertEquals('DESC', $restored->summary);
483
        $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat);
484
    }
485
 
11 efrain 486
    public function test_restore_course_fullname_in_existing_course_without_permissions(): void {
1 efrain 487
        global $DB;
488
        $this->resetAfterTest();
489
        $dg = $this->getDataGenerator();
490
        $u1 = $dg->create_user();
491
 
492
        $managers = get_archetype_roles('manager');
493
        $manager = array_shift($managers);
494
        $roleid = $this->create_role_with_caps('moodle/course:changefullname', CAP_PROHIBIT);
495
        $dg->role_assign($manager->id, $u1->id);
496
        $dg->role_assign($roleid, $u1->id);
497
 
498
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
499
        $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]);
500
 
501
        // The fullname does not change.
502
        $backupid = $this->backup_course($c1->id);
503
        $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
504
        $this->assertEquals('SN_1', $restored->shortname);
505
        $this->assertEquals($c2->fullname, $restored->fullname);
506
        $this->assertEquals('DESC', $restored->summary);
507
        $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat);
508
    }
509
 
11 efrain 510
    public function test_restore_course_summary_in_existing_course_without_permissions(): void {
1 efrain 511
        global $DB;
512
        $this->resetAfterTest();
513
        $dg = $this->getDataGenerator();
514
        $u1 = $dg->create_user();
515
 
516
        $managers = get_archetype_roles('manager');
517
        $manager = array_shift($managers);
518
        $roleid = $this->create_role_with_caps('moodle/course:changesummary', CAP_PROHIBIT);
519
        $dg->role_assign($manager->id, $u1->id);
520
        $dg->role_assign($roleid, $u1->id);
521
 
522
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
523
        $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]);
524
 
525
        // The summary and format do not change.
526
        $backupid = $this->backup_course($c1->id);
527
        $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
528
        $this->assertEquals('SN_1', $restored->shortname);
529
        $this->assertEquals('FN copy 1', $restored->fullname);
530
        $this->assertEquals($c2->summary, $restored->summary);
531
        $this->assertEquals($c2->summaryformat, $restored->summaryformat);
532
    }
533
 
11 efrain 534
    public function test_restore_course_startdate_in_existing_course_without_permissions(): void {
1 efrain 535
        global $DB;
536
        $this->resetAfterTest();
537
        $dg = $this->getDataGenerator();
538
 
539
        $u1 = $dg->create_user();
540
        $managers = get_archetype_roles('manager');
541
        $manager = array_shift($managers);
542
        $roleid = $this->create_role_with_caps('moodle/restore:rolldates', CAP_PROHIBIT);
543
        $dg->role_assign($manager->id, $u1->id);
544
        $dg->role_assign($roleid, $u1->id);
545
 
546
        // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date.
547
        $startdate1 = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016.
548
        $startdate2 = mktime(12, 0, 0, 1, 13, 2000); // 13-Jan-2000.
549
        $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE,
550
            'startdate' => $startdate1]);
551
        $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]);
552
        $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN,
553
            'startdate' => $startdate2]);
554
        $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]);
555
 
556
        // The startdate does not change.
557
        $backupid = $this->backup_course($c1->id);
558
        $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
559
        $this->assertEquals('SN_1', $restored->shortname);
560
        $this->assertEquals('FN copy 1', $restored->fullname);
561
        $this->assertEquals('DESC', $restored->summary);
562
        $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat);
563
        $this->assertEquals($startdate2, $restored->startdate);
564
 
565
        // Now course c2 has two chats - one ('Second') was already there and one ('First') was restored from the backup.
566
        // Start date of the restored chat ('First') was changed to be 1 week after the c2 start date.
567
        $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]);
568
        $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]);
569
        $this->assertNotEquals($chat1->chattime, $restoredchat1->chattime);
570
        $this->assertEquals($chat2->chattime, $restoredchat2->chattime);
571
        $this->assertEquals($c2->startdate + 1 * WEEKSECS, $restoredchat2->chattime);
572
    }
573
 
574
    /**
575
     * Tests course restore with editor in course format.
576
     *
577
     * @author Matthew Hilton
578
     * @covers \core_courseformat
579
     */
11 efrain 580
    public function test_restore_editor_courseformat(): void {
1 efrain 581
        $this->resetAfterTest();
582
 
583
        // Setup user with restore permissions.
584
        $dg = $this->getDataGenerator();
585
        $u1 = $dg->create_user();
586
 
587
        $managers = get_archetype_roles('manager');
588
        $manager = array_shift($managers);
589
        $dg->role_assign($manager->id, $u1->id);
590
 
591
        // Create a course with an editor item in the course format.
592
        $courseformatoptiondata = (object) [
593
            "hideoddsections" => 1,
594
            'summary_editor' => [
595
                'text' => '<p>Somewhere over the rainbow</p><p>The <b>quick</b> brown fox jumpos over the lazy dog.</p>',
596
                'format' => 1
597
            ]
598
        ];
599
        $course1 = $dg->create_course(['format' => 'theunittest']);
600
        $course2 = $dg->create_course(['format' => 'theunittest']);
601
        $this->assertEquals('theunittest', $course1->format);
602
        course_create_sections_if_missing($course1, array(0, 1));
603
 
604
        // Set the course format.
605
        $courseformat = course_get_format($course1);
606
        $courseformat->update_course_format_options($courseformatoptiondata);
607
 
608
        // Backup and restore the course.
609
        $backupid = $this->backup_course($course1->id);
610
        $this->restore_to_existing_course($backupid, $course2->id, $u1->id);
611
 
612
        // Get the restored course format.
613
        $restoredformat = course_get_format($course2);
614
        $restoredformatoptions = $restoredformat->get_format_options();
615
 
616
        $this->assertEqualsCanonicalizing($courseformatoptiondata, (object) $restoredformatoptions);
617
    }
618
}