MDL-64506 phpunit: Update unit tests to use classic
[moodle.git] / lib / tests / upgradelib_test.php
CommitLineData
6b7df0b5
EL
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/**
f5700877 18 * Unit tests for the lib/upgradelib.php library.
6b7df0b5
EL
19 *
20 * @package core
21 * @category phpunit
22 * @copyright 2013 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29require_once($CFG->libdir.'/upgradelib.php');
03d174d7 30require_once($CFG->libdir.'/db/upgradelib.php');
6b7df0b5 31
6b7df0b5 32/**
f5700877 33 * Tests various classes and functions in upgradelib.php library.
6b7df0b5 34 */
f5700877 35class core_upgradelib_testcase extends advanced_testcase {
6b7df0b5
EL
36
37 /**
38 * Test the {@link upgrade_stale_php_files_present() function
39 */
40 public function test_upgrade_stale_php_files_present() {
41 // Just call the function, must return bool false always
42 // if there aren't any old files in the codebase.
43 $this->assertFalse(upgrade_stale_php_files_present());
44 }
2a9d7a42 45
2a9d7a42
DP
46 /**
47 * Populate some fake grade items into the database with specified
48 * sortorder and course id.
49 *
50 * NOTE: This function doesn't make much attempt to respect the
51 * gradebook internals, its simply used to fake some data for
52 * testing the upgradelib function. Please don't use it for other
53 * purposes.
54 *
55 * @param int $courseid id of course
56 * @param int $sortorder numeric sorting order of item
57 * @return stdClass grade item object from the database.
58 */
59 private function insert_fake_grade_item_sortorder($courseid, $sortorder) {
60 global $DB, $CFG;
61 require_once($CFG->libdir.'/gradelib.php');
62
63 $item = new stdClass();
64 $item->courseid = $courseid;
65 $item->sortorder = $sortorder;
66 $item->gradetype = GRADE_TYPE_VALUE;
67 $item->grademin = 30;
68 $item->grademax = 110;
69 $item->itemnumber = 1;
70 $item->iteminfo = '';
71 $item->timecreated = time();
72 $item->timemodified = time();
73
74 $item->id = $DB->insert_record('grade_items', $item);
75
76 return $DB->get_record('grade_items', array('id' => $item->id));
77 }
119cf17e 78
156d0486
MG
79 public function test_upgrade_extra_credit_weightoverride() {
80 global $DB, $CFG;
81
82 $this->resetAfterTest(true);
83
1405f010
EL
84 require_once($CFG->libdir . '/db/upgradelib.php');
85
156d0486
MG
86 $c = array();
87 $a = array();
88 $gi = array();
89 for ($i=0; $i<5; $i++) {
90 $c[$i] = $this->getDataGenerator()->create_course();
91 $a[$i] = array();
92 $gi[$i] = array();
93 for ($j=0;$j<3;$j++) {
94 $a[$i][$j] = $this->getDataGenerator()->create_module('assign', array('course' => $c[$i], 'grade' => 100));
95 $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $a[$i][$j]->id,
96 'courseid' => $c[$i]->id, 'itemnumber' => 0);
97 $gi[$i][$j] = grade_item::fetch($giparams);
98 }
99 }
100
101 // Case 1: Course $c[0] has aggregation method different from natural.
102 $coursecategory = grade_category::fetch_course_category($c[0]->id);
103 $coursecategory->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN;
104 $coursecategory->update();
105 $gi[0][1]->aggregationcoef = 1;
106 $gi[0][1]->update();
107 $gi[0][2]->weightoverride = 1;
108 $gi[0][2]->update();
109
110 // Case 2: Course $c[1] has neither extra credits nor overrides
111
112 // Case 3: Course $c[2] has extra credits but no overrides
113 $gi[2][1]->aggregationcoef = 1;
114 $gi[2][1]->update();
115
116 // Case 4: Course $c[3] has no extra credits and has overrides
117 $gi[3][2]->weightoverride = 1;
118 $gi[3][2]->update();
119
120 // Case 5: Course $c[4] has both extra credits and overrides
121 $gi[4][1]->aggregationcoef = 1;
122 $gi[4][1]->update();
123 $gi[4][2]->weightoverride = 1;
124 $gi[4][2]->update();
125
126 // Run the upgrade script and make sure only course $c[4] was marked as needed to be fixed.
127 upgrade_extra_credit_weightoverride();
128
129 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[0]->id}));
130 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[1]->id}));
131 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[2]->id}));
132 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[3]->id}));
133 $this->assertEquals(20150619, $CFG->{'gradebook_calculations_freeze_' . $c[4]->id});
134
135 set_config('gradebook_calculations_freeze_' . $c[4]->id, null);
136
137 // Run the upgrade script for a single course only.
138 upgrade_extra_credit_weightoverride($c[0]->id);
139 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[0]->id}));
140 upgrade_extra_credit_weightoverride($c[4]->id);
141 $this->assertEquals(20150619, $CFG->{'gradebook_calculations_freeze_' . $c[4]->id});
142 }
716c0810
AG
143
144 /**
145 * Test the upgrade function for flagging courses with calculated grade item problems.
146 */
316c560c 147 public function test_upgrade_calculated_grade_items_freeze() {
716c0810 148 global $DB, $CFG;
1405f010 149
716c0810
AG
150 $this->resetAfterTest();
151
1405f010
EL
152 require_once($CFG->libdir . '/db/upgradelib.php');
153
716c0810
AG
154 // Create a user.
155 $user = $this->getDataGenerator()->create_user();
156
157 // Create a couple of courses.
158 $course1 = $this->getDataGenerator()->create_course();
159 $course2 = $this->getDataGenerator()->create_course();
160 $course3 = $this->getDataGenerator()->create_course();
161
162 // Enrol the user in the courses.
163 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
164 $maninstance1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST);
165 $maninstance2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST);
166 $maninstance3 = $DB->get_record('enrol', array('courseid' => $course3->id, 'enrol' => 'manual'), '*', MUST_EXIST);
167 $manual = enrol_get_plugin('manual');
168 $manual->enrol_user($maninstance1, $user->id, $studentrole->id);
169 $manual->enrol_user($maninstance2, $user->id, $studentrole->id);
170 $manual->enrol_user($maninstance3, $user->id, $studentrole->id);
171
172 // To create the data we need we freeze the grade book to use the old behaviour.
173 set_config('gradebook_calculations_freeze_' . $course1->id, 20150627);
174 set_config('gradebook_calculations_freeze_' . $course2->id, 20150627);
175 set_config('gradebook_calculations_freeze_' . $course3->id, 20150627);
176 $CFG->grade_minmaxtouse = 2;
177
178 // Creating a category for a grade item.
179 $gradecategory = new grade_category();
180 $gradecategory->fullname = 'calculated grade category';
181 $gradecategory->courseid = $course1->id;
182 $gradecategory->insert();
183 $gradecategoryid = $gradecategory->id;
184
185 // This is a manual grade item.
186 $gradeitem = new grade_item();
187 $gradeitem->itemname = 'grade item one';
188 $gradeitem->itemtype = 'manual';
189 $gradeitem->categoryid = $gradecategoryid;
190 $gradeitem->courseid = $course1->id;
191 $gradeitem->idnumber = 'gi1';
192 $gradeitem->insert();
193
194 // Changing the category into a calculated grade category.
195 $gradecategoryitem = grade_item::fetch(array('iteminstance' => $gradecategory->id));
196 $gradecategoryitem->calculation = '=##gi' . $gradeitem->id . '##/2';
197 $gradecategoryitem->update();
198
199 // Setting a grade for the student.
200 $grade = $gradeitem->get_grade($user->id, true);
201 $grade->finalgrade = 50;
202 $grade->update();
203 // Creating all the grade_grade items.
204 grade_regrade_final_grades($course1->id);
205 // Updating the grade category to a new grade max and min.
206 $gradecategoryitem->grademax = 50;
207 $gradecategoryitem->grademin = 5;
208 $gradecategoryitem->update();
209
210 // Different manual grade item for course 2. We are creating a course with a calculated grade item that has a grade max of
211 // 50. The grade_grade will have a rawgrademax of 100 regardless.
212 $gradeitem = new grade_item();
213 $gradeitem->itemname = 'grade item one';
214 $gradeitem->itemtype = 'manual';
215 $gradeitem->courseid = $course2->id;
216 $gradeitem->idnumber = 'gi1';
217 $gradeitem->grademax = 25;
218 $gradeitem->insert();
219
220 // Calculated grade item for course 2.
221 $calculatedgradeitem = new grade_item();
222 $calculatedgradeitem->itemname = 'calculated grade';
223 $calculatedgradeitem->itemtype = 'manual';
224 $calculatedgradeitem->courseid = $course2->id;
225 $calculatedgradeitem->calculation = '=##gi' . $gradeitem->id . '##*2';
226 $calculatedgradeitem->grademax = 50;
227 $calculatedgradeitem->insert();
228
229 // Assigning a grade for the user.
230 $grade = $gradeitem->get_grade($user->id, true);
231 $grade->finalgrade = 10;
232 $grade->update();
233
234 // Setting all of the grade_grade items.
235 grade_regrade_final_grades($course2->id);
236
237 // Different manual grade item for course 3. We are creating a course with a calculated grade item that has a grade max of
238 // 50. The grade_grade will have a rawgrademax of 100 regardless.
239 $gradeitem = new grade_item();
240 $gradeitem->itemname = 'grade item one';
241 $gradeitem->itemtype = 'manual';
242 $gradeitem->courseid = $course3->id;
243 $gradeitem->idnumber = 'gi1';
244 $gradeitem->grademax = 25;
245 $gradeitem->insert();
246
247 // Calculated grade item for course 2.
248 $calculatedgradeitem = new grade_item();
249 $calculatedgradeitem->itemname = 'calculated grade';
250 $calculatedgradeitem->itemtype = 'manual';
251 $calculatedgradeitem->courseid = $course3->id;
252 $calculatedgradeitem->calculation = '=##gi' . $gradeitem->id . '##*2';
253 $calculatedgradeitem->grademax = 50;
254 $calculatedgradeitem->insert();
255
256 // Assigning a grade for the user.
257 $grade = $gradeitem->get_grade($user->id, true);
258 $grade->finalgrade = 10;
259 $grade->update();
260
261 // Setting all of the grade_grade items.
262 grade_regrade_final_grades($course3->id);
263 // Need to do this first before changing the other courses, otherwise they will be flagged too early.
264 set_config('gradebook_calculations_freeze_' . $course3->id, null);
265 upgrade_calculated_grade_items($course3->id);
266 $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course3->id});
267
268 // Change the setting back to null.
269 set_config('gradebook_calculations_freeze_' . $course1->id, null);
270 set_config('gradebook_calculations_freeze_' . $course2->id, null);
271 // Run the upgrade.
272 upgrade_calculated_grade_items();
273 // The setting should be set again after the upgrade.
274 $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course1->id});
275 $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course2->id});
276 }
316c560c
AG
277
278 function test_upgrade_calculated_grade_items_regrade() {
279 global $DB, $CFG;
1405f010 280
316c560c
AG
281 $this->resetAfterTest();
282
1405f010
EL
283 require_once($CFG->libdir . '/db/upgradelib.php');
284
316c560c
AG
285 // Create a user.
286 $user = $this->getDataGenerator()->create_user();
287
288 // Create a course.
289 $course = $this->getDataGenerator()->create_course();
290
291 // Enrol the user in the course.
292 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
293 $maninstance1 = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
294 $manual = enrol_get_plugin('manual');
295 $manual->enrol_user($maninstance1, $user->id, $studentrole->id);
296
297 set_config('upgrade_calculatedgradeitemsonlyregrade', 1);
298
299 // Creating a category for a grade item.
300 $gradecategory = new grade_category();
301 $gradecategory->fullname = 'calculated grade category';
302 $gradecategory->courseid = $course->id;
303 $gradecategory->insert();
304 $gradecategoryid = $gradecategory->id;
305
306 // This is a manual grade item.
307 $gradeitem = new grade_item();
308 $gradeitem->itemname = 'grade item one';
309 $gradeitem->itemtype = 'manual';
310 $gradeitem->categoryid = $gradecategoryid;
311 $gradeitem->courseid = $course->id;
312 $gradeitem->idnumber = 'gi1';
313 $gradeitem->insert();
314
315 // Changing the category into a calculated grade category.
316 $gradecategoryitem = grade_item::fetch(array('iteminstance' => $gradecategory->id));
317 $gradecategoryitem->calculation = '=##gi' . $gradeitem->id . '##/2';
318 $gradecategoryitem->grademax = 50;
319 $gradecategoryitem->grademin = 15;
320 $gradecategoryitem->update();
321
322 // Setting a grade for the student.
323 $grade = $gradeitem->get_grade($user->id, true);
324 $grade->finalgrade = 50;
325 $grade->update();
326
327 grade_regrade_final_grades($course->id);
328 $grade = grade_grade::fetch(array('itemid' => $gradecategoryitem->id, 'userid' => $user->id));
329 $grade->rawgrademax = 100;
330 $grade->rawgrademin = 0;
331 $grade->update();
332 $this->assertNotEquals($gradecategoryitem->grademax, $grade->rawgrademax);
333 $this->assertNotEquals($gradecategoryitem->grademin, $grade->rawgrademin);
334
335 // This is the function that we are testing. If we comment out this line, then the test fails because the grade items
336 // are not flagged for regrading.
337 upgrade_calculated_grade_items();
338 grade_regrade_final_grades($course->id);
339
340 $grade = grade_grade::fetch(array('itemid' => $gradecategoryitem->id, 'userid' => $user->id));
341
342 $this->assertEquals($gradecategoryitem->grademax, $grade->rawgrademax);
343 $this->assertEquals($gradecategoryitem->grademin, $grade->rawgrademin);
344 }
0d1e5456 345
70dfd48f
AG
346 /**
347 * Test that the upgrade script correctly flags courses to be frozen due to letter boundary problems.
348 */
349 public function test_upgrade_course_letter_boundary() {
350 global $CFG, $DB;
351 $this->resetAfterTest(true);
352
ece791db
DM
353 require_once($CFG->libdir . '/db/upgradelib.php');
354
70dfd48f
AG
355 // Create a user.
356 $user = $this->getDataGenerator()->create_user();
357
358 // Create some courses.
359 $courses = array();
360 $contexts = array();
97a85bf6 361 for ($i = 0; $i < 45; $i++) {
70dfd48f
AG
362 $course = $this->getDataGenerator()->create_course();
363 $context = context_course::instance($course->id);
ece791db 364 if (in_array($i, array(2, 5, 10, 13, 14, 19, 23, 25, 30, 34, 36))) {
70dfd48f
AG
365 // Assign good letter boundaries.
366 $this->assign_good_letter_boundary($context->id);
367 }
ece791db 368 if (in_array($i, array(3, 6, 11, 15, 20, 24, 26, 31, 35))) {
70dfd48f
AG
369 // Assign bad letter boundaries.
370 $this->assign_bad_letter_boundary($context->id);
371 }
372
97a85bf6 373 if (in_array($i, array(3, 9, 10, 11, 18, 19, 20, 29, 30, 31, 40))) {
70dfd48f 374 grade_set_setting($course->id, 'displaytype', '3');
ece791db 375 } else if (in_array($i, array(8, 17, 28))) {
70dfd48f
AG
376 grade_set_setting($course->id, 'displaytype', '2');
377 }
378
97a85bf6
AG
379 if (in_array($i, array(37, 43))) {
380 // Show.
381 grade_set_setting($course->id, 'report_user_showlettergrade', '1');
382 } else if (in_array($i, array(38, 42))) {
383 // Hide.
384 grade_set_setting($course->id, 'report_user_showlettergrade', '0');
70dfd48f
AG
385 }
386
97a85bf6
AG
387 $assignrow = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'name' => 'Test!'));
388 $gi = grade_item::fetch(
389 array('itemtype' => 'mod',
390 'itemmodule' => 'assign',
391 'iteminstance' => $assignrow->id,
392 'courseid' => $course->id));
393 if (in_array($i, array(6, 13, 14, 15, 23, 24, 34, 35, 36, 41))) {
394 grade_item::set_properties($gi, array('display' => 3));
395 $gi->update();
396 } else if (in_array($i, array(12, 21, 32))) {
397 grade_item::set_properties($gi, array('display' => 2));
398 $gi->update();
399 }
400 $gradegrade = new grade_grade();
401 $gradegrade->itemid = $gi->id;
402 $gradegrade->userid = $user->id;
403 $gradegrade->rawgrade = 55.5563;
404 $gradegrade->finalgrade = 55.5563;
405 $gradegrade->rawgrademax = 100;
406 $gradegrade->rawgrademin = 0;
407 $gradegrade->timecreated = time();
408 $gradegrade->timemodified = time();
409 $gradegrade->insert();
410
70dfd48f
AG
411 $contexts[] = $context;
412 $courses[] = $course;
413 }
414
415 upgrade_course_letter_boundary();
416
417 // No system setting for grade letter boundaries.
418 // [0] A course with no letter boundaries.
419 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[0]->id}));
420 // [1] A course with letter boundaries which are default.
421 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[1]->id}));
422 // [2] A course with letter boundaries which are custom but not affected.
423 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[2]->id}));
424 // [3] A course with letter boundaries which are custom and will be affected.
41abbbbd 425 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[3]->id});
70dfd48f
AG
426 // [4] A course with no letter boundaries, but with a grade item with letter boundaries which are default.
427 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[4]->id}));
428 // [5] A course with no letter boundaries, but with a grade item with letter boundaries which are not default, but not affected.
429 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[5]->id}));
430 // [6] A course with no letter boundaries, but with a grade item with letter boundaries which are not default which will be affected.
41abbbbd 431 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[6]->id});
70dfd48f
AG
432
433 // System setting for grade letter boundaries (default).
434 set_config('grade_displaytype', '3');
97a85bf6 435 for ($i = 0; $i < 45; $i++) {
ece791db
DM
436 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id);
437 }
70dfd48f 438 upgrade_course_letter_boundary();
ece791db 439
70dfd48f
AG
440 // [7] A course with no grade display settings for the course or grade items.
441 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[7]->id}));
442 // [8] A course with grade display settings, but for something that isn't letters.
443 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[8]->id}));
444 // [9] A course with grade display settings of letters which are default.
445 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[9]->id}));
446 // [10] A course with grade display settings of letters which are not default, but not affected.
447 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[10]->id}));
448 // [11] A course with grade display settings of letters which are not default, which will be affected.
41abbbbd 449 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[11]->id});
70dfd48f
AG
450 // [12] A grade item with display settings that are not letters.
451 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[12]->id}));
452 // [13] A grade item with display settings of letters which are default.
453 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[13]->id}));
454 // [14] A grade item with display settings of letters which are not default, but not affected.
455 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[14]->id}));
456 // [15] A grade item with display settings of letters which are not default, which will be affected.
41abbbbd 457 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[15]->id});
70dfd48f
AG
458
459 // System setting for grade letter boundaries (custom with problem).
460 $systemcontext = context_system::instance();
461 $this->assign_bad_letter_boundary($systemcontext->id);
97a85bf6 462 for ($i = 0; $i < 45; $i++) {
ece791db
DM
463 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id);
464 }
70dfd48f
AG
465 upgrade_course_letter_boundary();
466
467 // [16] A course with no grade display settings for the course or grade items.
41abbbbd 468 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[16]->id});
70dfd48f
AG
469 // [17] A course with grade display settings, but for something that isn't letters.
470 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[17]->id}));
471 // [18] A course with grade display settings of letters which are default.
41abbbbd 472 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[18]->id});
70dfd48f
AG
473 // [19] A course with grade display settings of letters which are not default, but not affected.
474 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[19]->id}));
475 // [20] A course with grade display settings of letters which are not default, which will be affected.
41abbbbd 476 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[20]->id});
70dfd48f 477 // [21] A grade item with display settings which are not letters. Grade total will be affected so should be frozen.
41abbbbd 478 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[21]->id});
70dfd48f 479 // [22] A grade item with display settings of letters which are default.
41abbbbd 480 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[22]->id});
70dfd48f
AG
481 // [23] A grade item with display settings of letters which are not default, but not affected. Course uses new letter boundary setting.
482 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[23]->id}));
483 // [24] A grade item with display settings of letters which are not default, which will be affected.
41abbbbd 484 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[24]->id});
70dfd48f
AG
485 // [25] A course which is using the default grade display setting, but has updated the grade letter boundary (not 57) Should not be frozen.
486 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[25]->id}));
487 // [26] A course that is using the default display setting (letters) and altered the letter boundary with 57. Should be frozen.
41abbbbd 488 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[26]->id});
ece791db
DM
489
490 // System setting not showing letters.
491 set_config('grade_displaytype', '2');
97a85bf6 492 for ($i = 0; $i < 45; $i++) {
ece791db
DM
493 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id);
494 }
495 upgrade_course_letter_boundary();
496
497 // [27] A course with no grade display settings for the course or grade items.
498 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[27]->id}));
499 // [28] A course with grade display settings, but for something that isn't letters.
500 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[28]->id}));
501 // [29] A course with grade display settings of letters which are default.
41abbbbd 502 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[29]->id});
ece791db
DM
503 // [30] A course with grade display settings of letters which are not default, but not affected.
504 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[30]->id}));
505 // [31] A course with grade display settings of letters which are not default, which will be affected.
41abbbbd 506 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[31]->id});
ece791db
DM
507 // [32] A grade item with display settings which are not letters.
508 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[32]->id}));
509 // [33] All system defaults.
510 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[33]->id}));
511 // [34] A grade item with display settings of letters which are not default, but not affected. Course uses new letter boundary setting.
512 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[34]->id}));
513 // [35] A grade item with display settings of letters which are not default, which will be affected.
41abbbbd 514 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[35]->id});
ece791db
DM
515 // [36] A course with grade display settings of letters with modified and good boundary (not 57) Should not be frozen.
516 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[36]->id}));
97a85bf6
AG
517
518 // Previous site conditions still exist.
519 for ($i = 0; $i < 45; $i++) {
520 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id);
521 }
522 upgrade_course_letter_boundary();
523
524 // [37] Site setting for not showing the letter column and course setting set to show (frozen).
525 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[37]->id});
526 // [38] Site setting for not showing the letter column and course setting set to hide.
527 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[38]->id}));
528 // [39] Site setting for not showing the letter column and course setting set to default.
529 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[39]->id}));
530 // [40] Site setting for not showing the letter column and course setting set to default. Course display set to letters (frozen).
531 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[40]->id});
532 // [41] Site setting for not showing the letter column and course setting set to default. Grade item display set to letters (frozen).
533 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[41]->id});
534
535 // Previous site conditions still exist.
536 for ($i = 0; $i < 45; $i++) {
537 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id);
538 }
539 set_config('grade_report_user_showlettergrade', '1');
540 upgrade_course_letter_boundary();
541
542 // [42] Site setting for showing the letter column, but course setting set to hide.
543 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[42]->id}));
544 // [43] Site setting for showing the letter column and course setting set to show (frozen).
545 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[43]->id});
546 // [44] Site setting for showing the letter column and course setting set to default (frozen).
547 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[44]->id});
70dfd48f
AG
548 }
549
550 /**
551 * Test upgrade_letter_boundary_needs_freeze function.
552 */
553 public function test_upgrade_letter_boundary_needs_freeze() {
ece791db
DM
554 global $CFG;
555
70dfd48f
AG
556 $this->resetAfterTest();
557
ece791db
DM
558 require_once($CFG->libdir . '/db/upgradelib.php');
559
70dfd48f
AG
560 $courses = array();
561 $contexts = array();
562 for ($i = 0; $i < 3; $i++) {
563 $courses[] = $this->getDataGenerator()->create_course();
564 $contexts[] = context_course::instance($courses[$i]->id);
565 }
566
567 // Course one is not using a letter boundary.
568 $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[0]));
569
570 // Let's make course 2 use the bad boundary.
571 $this->assign_bad_letter_boundary($contexts[1]->id);
572 $this->assertTrue(upgrade_letter_boundary_needs_freeze($contexts[1]));
573 // Course 3 has letter boundaries that are fine.
574 $this->assign_good_letter_boundary($contexts[2]->id);
575 $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[2]));
576 // Try the system context not using a letter boundary.
577 $systemcontext = context_system::instance();
578 $this->assertFalse(upgrade_letter_boundary_needs_freeze($systemcontext));
579 }
580
581 /**
582 * Assigns letter boundaries with comparison problems.
583 *
584 * @param int $contextid Context ID.
585 */
586 private function assign_bad_letter_boundary($contextid) {
587 global $DB;
588 $newlettersscale = array(
589 array('contextid' => $contextid, 'lowerboundary' => 90.00000, 'letter' => 'A'),
590 array('contextid' => $contextid, 'lowerboundary' => 85.00000, 'letter' => 'A-'),
591 array('contextid' => $contextid, 'lowerboundary' => 80.00000, 'letter' => 'B+'),
592 array('contextid' => $contextid, 'lowerboundary' => 75.00000, 'letter' => 'B'),
593 array('contextid' => $contextid, 'lowerboundary' => 70.00000, 'letter' => 'B-'),
594 array('contextid' => $contextid, 'lowerboundary' => 65.00000, 'letter' => 'C+'),
595 array('contextid' => $contextid, 'lowerboundary' => 57.00000, 'letter' => 'C'),
596 array('contextid' => $contextid, 'lowerboundary' => 50.00000, 'letter' => 'C-'),
597 array('contextid' => $contextid, 'lowerboundary' => 40.00000, 'letter' => 'D+'),
598 array('contextid' => $contextid, 'lowerboundary' => 25.00000, 'letter' => 'D'),
599 array('contextid' => $contextid, 'lowerboundary' => 0.00000, 'letter' => 'F'),
600 );
ece791db
DM
601
602 $DB->delete_records('grade_letters', array('contextid' => $contextid));
70dfd48f
AG
603 foreach ($newlettersscale as $record) {
604 // There is no API to do this, so we have to manually insert into the database.
605 $DB->insert_record('grade_letters', $record);
606 }
607 }
608
609 /**
610 * Assigns letter boundaries with no comparison problems.
611 *
612 * @param int $contextid Context ID.
613 */
614 private function assign_good_letter_boundary($contextid) {
615 global $DB;
616 $newlettersscale = array(
617 array('contextid' => $contextid, 'lowerboundary' => 90.00000, 'letter' => 'A'),
618 array('contextid' => $contextid, 'lowerboundary' => 85.00000, 'letter' => 'A-'),
619 array('contextid' => $contextid, 'lowerboundary' => 80.00000, 'letter' => 'B+'),
620 array('contextid' => $contextid, 'lowerboundary' => 75.00000, 'letter' => 'B'),
621 array('contextid' => $contextid, 'lowerboundary' => 70.00000, 'letter' => 'B-'),
622 array('contextid' => $contextid, 'lowerboundary' => 65.00000, 'letter' => 'C+'),
623 array('contextid' => $contextid, 'lowerboundary' => 54.00000, 'letter' => 'C'),
624 array('contextid' => $contextid, 'lowerboundary' => 50.00000, 'letter' => 'C-'),
625 array('contextid' => $contextid, 'lowerboundary' => 40.00000, 'letter' => 'D+'),
626 array('contextid' => $contextid, 'lowerboundary' => 25.00000, 'letter' => 'D'),
627 array('contextid' => $contextid, 'lowerboundary' => 0.00000, 'letter' => 'F'),
628 );
ece791db
DM
629
630 $DB->delete_records('grade_letters', array('contextid' => $contextid));
70dfd48f
AG
631 foreach ($newlettersscale as $record) {
632 // There is no API to do this, so we have to manually insert into the database.
633 $DB->insert_record('grade_letters', $record);
634 }
635 }
f2330472
AA
636
637 /**
638 * Test libcurl custom check api.
639 */
640 public function test_check_libcurl_version() {
641 $supportedversion = 0x071304;
642 $curlinfo = curl_version();
643 $currentversion = $curlinfo['version_number'];
644
645 $result = new environment_results("custom_checks");
646 if ($currentversion < $supportedversion) {
647 $this->assertFalse(check_libcurl_version($result)->getStatus());
648 } else {
649 $this->assertNull(check_libcurl_version($result));
650 }
651 }
a5722727
MG
652
653 /**
654 * Create two pages with blocks, delete one page and make sure upgrade script deletes orphaned blocks
655 */
656 public function test_delete_block_positions() {
657 global $DB, $CFG;
658 require_once($CFG->dirroot . '/my/lib.php');
659 $this->resetAfterTest();
660
661 // Make sure each block on system dashboard page has a position.
662 $systempage = $DB->get_record('my_pages', array('userid' => null, 'private' => MY_PAGE_PRIVATE));
663 $systemcontext = context_system::instance();
664 $blockinstances = $DB->get_records('block_instances', array('parentcontextid' => $systemcontext->id,
665 'pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id));
666 $this->assertNotEmpty($blockinstances);
667 foreach ($blockinstances as $bi) {
668 $DB->insert_record('block_positions', ['subpage' => $systempage->id, 'pagetype' => 'my-index', 'contextid' => $systemcontext->id,
669 'blockinstanceid' => $bi->id, 'visible' => 1, 'weight' => $bi->defaultweight]);
670 }
671
672 // Create two users and make two copies of the system dashboard.
673 $user1 = $this->getDataGenerator()->create_user();
674 $user2 = $this->getDataGenerator()->create_user();
675 $page1 = my_copy_page($user1->id, MY_PAGE_PRIVATE, 'my-index');
676 $page2 = my_copy_page($user2->id, MY_PAGE_PRIVATE, 'my-index');
677
678 $context1 = context_user::instance($user1->id);
679 $context2 = context_user::instance($user2->id);
680
681 // Delete second page without deleting block positions.
682 $DB->delete_records('my_pages', ['id' => $page2->id]);
683
684 // Blocks are still here.
685 $this->assertEquals(count($blockinstances), $DB->count_records('block_positions', ['subpage' => $page1->id, 'pagetype' => 'my-index', 'contextid' => $context1->id]));
686 $this->assertEquals(count($blockinstances), $DB->count_records('block_positions', ['subpage' => $page2->id, 'pagetype' => 'my-index', 'contextid' => $context2->id]));
687
688 // Run upgrade script that should delete orphaned block_positions.
689 upgrade_block_positions();
690
691 // First user still has all his block_positions, second user does not.
692 $this->assertEquals(count($blockinstances), $DB->count_records('block_positions', ['subpage' => $page1->id, 'pagetype' => 'my-index', 'contextid' => $context1->id]));
693 $this->assertEquals(0, $DB->count_records('block_positions', ['subpage' => $page2->id, 'pagetype' => 'my-index']));
694 }
31bd1023
DM
695
696 /**
697 * Test the conversion of auth plugin settings names.
698 */
699 public function test_upgrade_fix_config_auth_plugin_names() {
700 $this->resetAfterTest();
701
702 // Let the plugin auth_foo use legacy format only.
703 set_config('name1', 'val1', 'auth/foo');
704 set_config('name2', 'val2', 'auth/foo');
705
706 // Let the plugin auth_bar use new format only.
707 set_config('name1', 'val1', 'auth_bar');
708 set_config('name2', 'val2', 'auth_bar');
709
710 // Let the plugin auth_baz use a mix of legacy and new format, with no conflicts.
711 set_config('name1', 'val1', 'auth_baz');
712 set_config('name1', 'val1', 'auth/baz');
713 set_config('name2', 'val2', 'auth/baz');
714 set_config('name3', 'val3', 'auth_baz');
715
716 // Let the plugin auth_qux use a mix of legacy and new format, with conflicts.
717 set_config('name1', 'val1', 'auth_qux');
718 set_config('name1', 'val2', 'auth/qux');
719
720 // Execute the migration.
721 upgrade_fix_config_auth_plugin_names('foo');
722 upgrade_fix_config_auth_plugin_names('bar');
723 upgrade_fix_config_auth_plugin_names('baz');
724 upgrade_fix_config_auth_plugin_names('qux');
725
726 // Assert that legacy settings are gone and no new were introduced.
727 $this->assertEmpty((array) get_config('auth/foo'));
728 $this->assertEmpty((array) get_config('auth/bar'));
729 $this->assertEmpty((array) get_config('auth/baz'));
730 $this->assertEmpty((array) get_config('auth/qux'));
731
732 // Assert values were simply kept where there was no conflict.
733 $this->assertSame('val1', get_config('auth_foo', 'name1'));
734 $this->assertSame('val2', get_config('auth_foo', 'name2'));
735
736 $this->assertSame('val1', get_config('auth_bar', 'name1'));
737 $this->assertSame('val2', get_config('auth_bar', 'name2'));
738
739 $this->assertSame('val1', get_config('auth_baz', 'name1'));
740 $this->assertSame('val2', get_config('auth_baz', 'name2'));
741 $this->assertSame('val3', get_config('auth_baz', 'name3'));
742
743 // Assert the new format took precedence in case of conflict.
744 $this->assertSame('val1', get_config('auth_qux', 'name1'));
745 }
e46fde42
JO
746
747 /**
748 * Create a collection of test themes to test determining parent themes.
749 *
750 * @return Url to the path containing the test themes
751 */
752 public function create_testthemes() {
753 global $CFG;
754
755 $themedircontent = [
756 'testtheme' => [
757 'config.php' => '<?php $THEME->name = "testtheme"; $THEME->parents = [""];',
758 ],
759 'childoftesttheme' => [
760 'config.php' => '<?php $THEME->name = "childofboost"; $THEME->parents = ["testtheme"];',
761 ],
762 'infinite' => [
763 'config.php' => '<?php $THEME->name = "infinite"; $THEME->parents = ["forever"];',
764 ],
765 'forever' => [
766 'config.php' => '<?php $THEME->name = "forever"; $THEME->parents = ["infinite", "childoftesttheme"];',
767 ],
768 'orphantheme' => [
769 'config.php' => '<?php $THEME->name = "orphantheme"; $THEME->parents = [];',
770 ],
771 'loop' => [
772 'config.php' => '<?php $THEME->name = "loop"; $THEME->parents = ["around"];',
773 ],
774 'around' => [
775 'config.php' => '<?php $THEME->name = "around"; $THEME->parents = ["loop"];',
776 ],
777 'themewithbrokenparent' => [
778 'config.php' => '<?php $THEME->name = "orphantheme"; $THEME->parents = ["nonexistent", "testtheme"];',
779 ],
780 ];
781 $vthemedir = \org\bovigo\vfs\vfsStream::setup('themes', null, $themedircontent);
782
783 return \org\bovigo\vfs\vfsStream::url('themes');
784 }
785
786 /**
787 * Test finding theme locations.
788 */
789 public function test_upgrade_find_theme_location() {
790 global $CFG;
791
792 $this->resetAfterTest();
793
794 $CFG->themedir = $this->create_testthemes();
795
796 $this->assertSame($CFG->dirroot . '/theme/boost', upgrade_find_theme_location('boost'));
e00f1c66 797 $this->assertSame($CFG->dirroot . '/theme/classic', upgrade_find_theme_location('classic'));
e46fde42
JO
798
799 $this->assertSame($CFG->themedir . '/testtheme', upgrade_find_theme_location('testtheme'));
800 $this->assertSame($CFG->themedir . '/childoftesttheme', upgrade_find_theme_location('childoftesttheme'));
801 }
802
803 /**
804 * Test figuring out if theme is or is a child of a certain theme.
805 */
806 public function test_upgrade_theme_is_from_family() {
807 global $CFG;
808
809 $this->resetAfterTest();
810
811 $CFG->themedir = $this->create_testthemes();
812
813 $this->assertTrue(upgrade_theme_is_from_family('boost', 'boost'), 'Boost is a boost theme');
e00f1c66
MM
814 $this->assertTrue(upgrade_theme_is_from_family('boost', 'classic'), 'Classic is a boost base theme');
815 $this->assertFalse(upgrade_theme_is_from_family('classic', 'boost'), 'Boost is not a classic theme');
e46fde42
JO
816
817 $this->assertTrue(upgrade_theme_is_from_family('testtheme', 'childoftesttheme'), 'childoftesttheme is a testtheme');
818 $this->assertFalse(upgrade_theme_is_from_family('testtheme', 'orphantheme'), 'ofphantheme is not a testtheme');
819 $this->assertTrue(upgrade_theme_is_from_family('testtheme', 'infinite'), 'Infinite loop with testtheme parent is true');
820 $this->assertFalse(upgrade_theme_is_from_family('testtheme', 'loop'), 'Infinite loop without testtheme parent is false');
821 $this->assertTrue(upgrade_theme_is_from_family('testtheme', 'themewithbrokenparent'), 'No error on broken parent');
822 }
8a844437
AG
823
824 /**
825 * Data provider of serialized string.
826 *
827 * @return array
828 */
829 public function serialized_strings_dataprovider() {
830 return [
831 'A configuration that uses the old object' => [
832 'O:6:"object":3:{s:4:"text";s:32:"Nothing that anyone cares about.";s:5:"title";s:16:"Really old block";s:6:"format";s:1:"1";}',
833 true,
834 'O:8:"stdClass":3:{s:4:"text";s:32:"Nothing that anyone cares about.";s:5:"title";s:16:"Really old block";s:6:"format";s:1:"1";}'
835 ],
836 'A configuration that uses stdClass' => [
837 'O:8:"stdClass":5:{s:5:"title";s:4:"Tags";s:12:"numberoftags";s:2:"80";s:12:"showstandard";s:1:"0";s:3:"ctx";s:3:"289";s:3:"rec";s:1:"1";}',
838 false,
839 'O:8:"stdClass":5:{s:5:"title";s:4:"Tags";s:12:"numberoftags";s:2:"80";s:12:"showstandard";s:1:"0";s:3:"ctx";s:3:"289";s:3:"rec";s:1:"1";}'
840 ],
841 'A setting I saw when importing a course with blocks from 1.9' => [
842 'N;',
843 false,
844 'N;'
845 ],
846 'An object in an object' => [
847 'O:6:"object":2:{s:2:"id";i:5;s:5:"other";O:6:"object":1:{s:4:"text";s:13:"something new";}}',
848 true,
849 'O:8:"stdClass":2:{s:2:"id";i:5;s:5:"other";O:8:"stdClass":1:{s:4:"text";s:13:"something new";}}'
850 ],
851 'An array with an object in it' => [
852 'a:3:{s:4:"name";s:4:"Test";s:10:"additional";O:6:"object":2:{s:2:"id";i:5;s:4:"info";s:18:"text in the object";}s:4:"type";i:1;}',
853 true,
854 'a:3:{s:4:"name";s:4:"Test";s:10:"additional";O:8:"stdClass":2:{s:2:"id";i:5;s:4:"info";s:18:"text in the object";}s:4:"type";i:1;}'
855 ]
856 ];
857 }
858
859 /**
860 * Test that objects in serialized strings will be changed over to stdClass.
861 *
862 * @dataProvider serialized_strings_dataprovider
863 * @param string $initialstring The initial serialized setting.
864 * @param bool $expectededited If the string is expected to be edited.
865 * @param string $expectedresult The expected serialized setting to be returned.
866 */
867 public function test_upgrade_fix_serialized_objects($initialstring, $expectededited, $expectedresult) {
868 list($edited, $resultstring) = upgrade_fix_serialized_objects($initialstring);
869 $this->assertEquals($expectededited, $edited);
870 $this->assertEquals($expectedresult, $resultstring);
871 }
872
873 /**
874 * Data provider for base64_encoded block instance config data.
875 */
876 public function encoded_strings_dataprovider() {
877 return [
878 'Normal data using stdClass' => [
879 'Tzo4OiJzdGRDbGFzcyI6NTp7czo1OiJ0aXRsZSI7czo0OiJUYWdzIjtzOjEyOiJudW1iZXJvZnRhZ3MiO3M6MjoiODAiO3M6MTI6InNob3dzdGFuZGFyZCI7czoxOiIwIjtzOjM6ImN0eCI7czozOiIyODkiO3M6MzoicmVjIjtzOjE6IjEiO30=',
880 'Tzo4OiJzdGRDbGFzcyI6NTp7czo1OiJ0aXRsZSI7czo0OiJUYWdzIjtzOjEyOiJudW1iZXJvZnRhZ3MiO3M6MjoiODAiO3M6MTI6InNob3dzdGFuZGFyZCI7czoxOiIwIjtzOjM6ImN0eCI7czozOiIyODkiO3M6MzoicmVjIjtzOjE6IjEiO30='
881 ],
882 'No data at all' => [
883 '',
884 ''
885 ],
886 'Old data using object' => [
887 'Tzo2OiJvYmplY3QiOjM6e3M6NDoidGV4dCI7czozMjoiTm90aGluZyB0aGF0IGFueW9uZSBjYXJlcyBhYm91dC4iO3M6NToidGl0bGUiO3M6MTY6IlJlYWxseSBvbGQgYmxvY2siO3M6NjoiZm9ybWF0IjtzOjE6IjEiO30=',
888 'Tzo4OiJzdGRDbGFzcyI6Mzp7czo0OiJ0ZXh0IjtzOjMyOiJOb3RoaW5nIHRoYXQgYW55b25lIGNhcmVzIGFib3V0LiI7czo1OiJ0aXRsZSI7czoxNjoiUmVhbGx5IG9sZCBibG9jayI7czo2OiJmb3JtYXQiO3M6MToiMSI7fQ=='
889 ]
890 ];
891 }
892
893 /**
894 * Check that entries in the block_instances table are coverted over correctly.
895 *
896 * @dataProvider encoded_strings_dataprovider
897 * @param string $original The original base64_encoded block config setting.
898 * @param string $expected The expected base64_encoded block config setting.
899 */
900 public function test_upgrade_fix_block_instance_configuration($original, $expected) {
901 global $DB;
902
903 $this->resetAfterTest();
904
905 $data = new stdClass();
906 $data->blockname = 'html';
907 $data->parentcontextid = 1;
908 $data->showinsubcontexts = 0;
909 $data->requirebytheme = 0;
910 $data->pagetypepattern = 'admin-setting-frontpagesettings';
911 $data->defaultregion = 'side-post';
912 $data->defaultweight = 1;
913 $data->timecreated = time();
914 $data->timemodified = time();
915
916 $data->configdata = $original;
917 $entryid = $DB->insert_record('block_instances', $data);
918 upgrade_fix_block_instance_configuration();
919 $record = $DB->get_record('block_instances', ['id' => $entryid]);
920 $this->assertEquals($expected, $record->configdata);
921 }
f408e1f8
IT
922
923 /**
924 * Check that orphaned files are deleted.
925 */
926 public function test_upgrade_delete_orphaned_file_records() {
927 global $DB, $CFG;
928 require_once($CFG->dirroot . '/repository/lib.php');
929
930 $this->resetAfterTest();
931 // Create user.
932 $generator = $this->getDataGenerator();
933 $user = $generator->create_user();
934 $this->setUser($user);
935 $usercontext = context_user::instance($user->id);
936 $syscontext = context_system::instance();
937
938 $fs = get_file_storage();
939
940 $userrepository = array();
941 $newstoredfile = array();
942 $repositorypluginname = array('user', 'areafiles');
943
944 // Create two repositories with one file in each.
945 foreach ($repositorypluginname as $key => $value) {
946 // Override repository permission.
947 $capability = 'repository/' . $value . ':view';
948 $guestroleid = $DB->get_field('role', 'id', array('shortname' => 'guest'));
949 assign_capability($capability, CAP_ALLOW, $guestroleid, $syscontext->id, true);
950
951 $args = array();
952 $args['type'] = $value;
953 $repos = repository::get_instances($args);
954 $userrepository[$key] = reset($repos);
955
956 $this->assertInstanceOf('repository', $userrepository[$key]);
957
958 $component = 'user';
959 $filearea = 'private';
960 $itemid = $key;
961 $filepath = '/';
962 $filename = 'userfile.txt';
963
964 $filerecord = array(
965 'contextid' => $usercontext->id,
966 'component' => $component,
967 'filearea' => $filearea,
968 'itemid' => $itemid,
969 'filepath' => $filepath,
970 'filename' => $filename,
971 );
972
973 $content = 'Test content';
974 $originalfile = $fs->create_file_from_string($filerecord, $content);
975 $this->assertInstanceOf('stored_file', $originalfile);
976
977 $newfilerecord = array(
978 'contextid' => $syscontext->id,
979 'component' => 'core',
980 'filearea' => 'phpunit',
981 'itemid' => $key,
982 'filepath' => $filepath,
983 'filename' => $filename,
984 );
985 $ref = $fs->pack_reference($filerecord);
986 $newstoredfile[$key] = $fs->create_file_from_reference($newfilerecord, $userrepository[$key]->id, $ref);
987
988 // Look for references by repository ID.
989 $files = $fs->get_external_files($userrepository[$key]->id);
990 $file = reset($files);
991 $this->assertEquals($file, $newstoredfile[$key]);
992 }
993
994 // Make one file orphaned by deleting first repository.
995 $DB->delete_records('repository_instances', array('id' => $userrepository[0]->id));
996 $DB->delete_records('repository_instance_config', array('instanceid' => $userrepository[0]->id));
997
998 upgrade_delete_orphaned_file_records();
999
1000 $files = $fs->get_external_files($userrepository[0]->id);
1001 $file = reset($files);
1002 $this->assertFalse($file);
1003
1004 $files = $fs->get_external_files($userrepository[1]->id);
1005 $file = reset($files);
1006 $this->assertEquals($file, $newstoredfile[1]);
1007 }
6b7df0b5 1008}