Commit | Line | Data |
---|---|---|
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 | ||
26 | defined('MOODLE_INTERNAL') || die(); | |
27 | ||
28 | global $CFG; | |
29 | require_once($CFG->libdir.'/upgradelib.php'); | |
03d174d7 | 30 | require_once($CFG->libdir.'/db/upgradelib.php'); |
6b7df0b5 | 31 | |
6b7df0b5 | 32 | /** |
f5700877 | 33 | * Tests various classes and functions in upgradelib.php library. |
6b7df0b5 | 34 | */ |
f5700877 | 35 | class 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 | } |