Merge branch 'MDL-56621-master-fix' of http://github.com/damyon/moodle
[moodle.git] / course / tests / restore_test.php
blob1b051efbbb37ed65622d4008ae02b07932115127
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.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * Course restore tests.
20 * @package core_course
21 * @copyright 2016 Frédéric Massart - FMCorz.net
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 defined('MOODLE_INTERNAL') || die();
26 global $CFG;
28 require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
29 require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
31 /**
32 * Course restore testcase.
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
38 class core_course_restore_testcase extends advanced_testcase {
40 /**
41 * Backup a course and return its backup ID.
43 * @param int $courseid The course ID.
44 * @param int $userid The user doing the backup.
45 * @return string
47 protected function backup_course($courseid, $userid = 2) {
48 globaL $CFG;
49 $packer = get_file_packer('application/vnd.moodle.backup');
51 $bc = new backup_controller(backup::TYPE_1COURSE, $courseid, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO,
52 backup::MODE_GENERAL, $userid);
53 $bc->execute_plan();
55 $results = $bc->get_results();
56 $results['backup_destination']->extract_to_pathname($packer, "$CFG->tempdir/backup/core_course_testcase");
58 $bc->destroy();
59 unset($bc);
60 return 'core_course_testcase';
63 /**
64 * Create a role with capabilities and permissions.
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.
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);
77 accesslib_clear_all_caches_for_unit_testing();
78 return $roleid;
81 /**
82 * Restore a course.
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.
89 protected function restore_course($backupid, $courseid, $userid) {
90 global $DB;
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);
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 $rc->execute_precheck();
102 $rc->execute_plan();
104 $course = $DB->get_record('course', array('id' => $rc->get_courseid()));
106 $rc->destroy();
107 unset($rc);
108 return $course;
112 * Restore a course to an existing course.
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.
119 protected function restore_to_existing_course($backupid, $courseid, $userid = 2) {
120 return $this->restore_course($backupid, $courseid, $userid);
124 * Restore a course to a new course.
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.
130 protected function restore_to_new_course($backupid, $userid = 2) {
131 return $this->restore_course($backupid, 0, $userid);
134 public function test_restore_existing_idnumber_in_new_course() {
135 $this->resetAfterTest();
137 $dg = $this->getDataGenerator();
138 $c1 = $dg->create_course(['idnumber' => 'ABC']);
139 $backupid = $this->backup_course($c1->id);
140 $c2 = $this->restore_to_new_course($backupid);
142 // The ID number is set empty.
143 $this->assertEquals('', $c2->idnumber);
146 public function test_restore_non_existing_idnumber_in_new_course() {
147 global $DB;
148 $this->resetAfterTest();
150 $dg = $this->getDataGenerator();
151 $c1 = $dg->create_course(['idnumber' => 'ABC']);
152 $backupid = $this->backup_course($c1->id);
154 $c1->idnumber = 'BCD';
155 $DB->update_record('course', $c1);
157 // The ID number changed.
158 $c2 = $this->restore_to_new_course($backupid);
159 $this->assertEquals('ABC', $c2->idnumber);
162 public function test_restore_existing_idnumber_in_existing_course() {
163 global $DB;
164 $this->resetAfterTest();
166 $dg = $this->getDataGenerator();
167 $c1 = $dg->create_course(['idnumber' => 'ABC']);
168 $c2 = $dg->create_course(['idnumber' => 'DEF']);
169 $backupid = $this->backup_course($c1->id);
171 // The ID number does not change.
172 $c2 = $this->restore_to_existing_course($backupid, $c2->id);
173 $this->assertEquals('DEF', $c2->idnumber);
175 $c1 = $DB->get_record('course', array('id' => $c1->id));
176 $this->assertEquals('ABC', $c1->idnumber);
179 public function test_restore_non_existing_idnumber_in_existing_course() {
180 global $DB;
181 $this->resetAfterTest();
183 $dg = $this->getDataGenerator();
184 $c1 = $dg->create_course(['idnumber' => 'ABC']);
185 $c2 = $dg->create_course(['idnumber' => 'DEF']);
186 $backupid = $this->backup_course($c1->id);
188 $c1->idnumber = 'XXX';
189 $DB->update_record('course', $c1);
191 // The ID number has changed.
192 $c2 = $this->restore_to_existing_course($backupid, $c2->id);
193 $this->assertEquals('ABC', $c2->idnumber);
196 public function test_restore_idnumber_in_existing_course_without_permissions() {
197 global $DB;
198 $this->resetAfterTest();
199 $dg = $this->getDataGenerator();
200 $u1 = $dg->create_user();
202 $managers = get_archetype_roles('manager');
203 $manager = array_shift($managers);
204 $roleid = $this->create_role_with_caps('moodle/course:changeidnumber', CAP_PROHIBIT);
205 $dg->role_assign($manager->id, $u1->id);
206 $dg->role_assign($roleid, $u1->id);
208 $c1 = $dg->create_course(['idnumber' => 'ABC']);
209 $c2 = $dg->create_course(['idnumber' => 'DEF']);
210 $backupid = $this->backup_course($c1->id);
212 $c1->idnumber = 'XXX';
213 $DB->update_record('course', $c1);
215 // The ID number does not change.
216 $c2 = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
217 $this->assertEquals('DEF', $c2->idnumber);
220 public function test_restore_course_info_in_new_course() {
221 global $DB;
222 $this->resetAfterTest();
223 $dg = $this->getDataGenerator();
225 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
226 $backupid = $this->backup_course($c1->id);
228 // The information is restored but adapted because names are already taken.
229 $c2 = $this->restore_to_new_course($backupid);
230 $this->assertEquals('SN_1', $c2->shortname);
231 $this->assertEquals('FN copy 1', $c2->fullname);
232 $this->assertEquals('DESC', $c2->summary);
233 $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat);
236 public function test_restore_course_info_in_existing_course() {
237 global $DB;
238 $this->resetAfterTest();
239 $dg = $this->getDataGenerator();
241 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
242 $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN]);
243 $backupid = $this->backup_course($c1->id);
245 // The information is restored but adapted because names are already taken.
246 $c2 = $this->restore_to_existing_course($backupid, $c2->id);
247 $this->assertEquals('SN_1', $c2->shortname);
248 $this->assertEquals('FN copy 1', $c2->fullname);
249 $this->assertEquals('DESC', $c2->summary);
250 $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat);
253 public function test_restore_course_shortname_in_existing_course_without_permissions() {
254 global $DB;
255 $this->resetAfterTest();
256 $dg = $this->getDataGenerator();
257 $u1 = $dg->create_user();
259 $managers = get_archetype_roles('manager');
260 $manager = array_shift($managers);
261 $roleid = $this->create_role_with_caps('moodle/course:changeshortname', CAP_PROHIBIT);
262 $dg->role_assign($manager->id, $u1->id);
263 $dg->role_assign($roleid, $u1->id);
265 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
266 $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]);
268 // The shortname does not change.
269 $backupid = $this->backup_course($c1->id);
270 $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
271 $this->assertEquals($c2->shortname, $restored->shortname);
272 $this->assertEquals('FN copy 1', $restored->fullname);
273 $this->assertEquals('DESC', $restored->summary);
274 $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat);
277 public function test_restore_course_fullname_in_existing_course_without_permissions() {
278 global $DB;
279 $this->resetAfterTest();
280 $dg = $this->getDataGenerator();
281 $u1 = $dg->create_user();
283 $managers = get_archetype_roles('manager');
284 $manager = array_shift($managers);
285 $roleid = $this->create_role_with_caps('moodle/course:changefullname', CAP_PROHIBIT);
286 $dg->role_assign($manager->id, $u1->id);
287 $dg->role_assign($roleid, $u1->id);
289 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
290 $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]);
292 // The fullname does not change.
293 $backupid = $this->backup_course($c1->id);
294 $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
295 $this->assertEquals('SN_1', $restored->shortname);
296 $this->assertEquals($c2->fullname, $restored->fullname);
297 $this->assertEquals('DESC', $restored->summary);
298 $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat);
301 public function test_restore_course_summary_in_existing_course_without_permissions() {
302 global $DB;
303 $this->resetAfterTest();
304 $dg = $this->getDataGenerator();
305 $u1 = $dg->create_user();
307 $managers = get_archetype_roles('manager');
308 $manager = array_shift($managers);
309 $roleid = $this->create_role_with_caps('moodle/course:changesummary', CAP_PROHIBIT);
310 $dg->role_assign($manager->id, $u1->id);
311 $dg->role_assign($roleid, $u1->id);
313 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE]);
314 $c2 = $dg->create_course(['shortname' => 'A1', 'fullname' => 'B1', 'summary' => 'C1', 'summaryformat' => FORMAT_PLAIN]);
316 // The summary and format do not change.
317 $backupid = $this->backup_course($c1->id);
318 $restored = $this->restore_to_existing_course($backupid, $c2->id, $u1->id);
319 $this->assertEquals('SN_1', $restored->shortname);
320 $this->assertEquals('FN copy 1', $restored->fullname);
321 $this->assertEquals($c2->summary, $restored->summary);
322 $this->assertEquals($c2->summaryformat, $restored->summaryformat);