MDL-22584 fixed non standard space char breaking file upgrades
[moodle.git] / lib / db / upgradelib.php
CommitLineData
117bd748 1<?php
42ff9ce6 2
5b4a78e2
PS
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Upgrade helper functions
20 *
42ff9ce6 21 * This file is used for special upgrade functions - for example groups and gradebook.
56a1a882 22 * These functions must use SQL and database related functions only- no other Moodle API,
42ff9ce6 23 * because it might depend on db structures that are not yet present during upgrade.
24 * (Do not use functions from accesslib.php, grades classes or group functions at all!)
5b4a78e2
PS
25 *
26 * @package core
27 * @subpackage admin
28 * @copyright 2007 Petr Skoda (http://skodak.org)
29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42ff9ce6 30 */
31
5b4a78e2
PS
32defined('MOODLE_INTERNAL') || die();
33
863850d2 34function upgrade_fix_category_depths() {
f33e1ed4 35 global $CFG, $DB;
863850d2 36
37 // first fix incorrect parents
38 $sql = "SELECT c.id
f33e1ed4 39 FROM {course_categories} c
40 WHERE c.parent > 0 AND c.parent NOT IN (SELECT pc.id FROM {course_categories} pc)";
41 if ($rs = $DB->get_recordset_sql($sql)) {
42 foreach ($rs as $cat) {
863850d2 43 $cat->depth = 1;
44 $cat->path = '/'.$cat->id;
45 $cat->parent = 0;
f33e1ed4 46 $DB->update_record('course_categories', $cat);
863850d2 47 }
f33e1ed4 48 $rs->close();
863850d2 49 }
50
51 // now add path and depth to top level categories
f33e1ed4 52 $sql = "UPDATE {course_categories}
245ac557 53 SET depth = 1, path = ".$DB->sql_concat("'/'", "id")."
863850d2 54 WHERE parent = 0";
f33e1ed4 55 $DB->execute($sql);
863850d2 56
57 // now fix all other levels - slow but works in all supported dbs
58 $parentdepth = 1;
f33e1ed4 59 while ($DB->record_exists('course_categories', array('depth'=>0))) {
863850d2 60 $sql = "SELECT c.id, pc.path
f33e1ed4 61 FROM {course_categories} c, {course_categories} pc
62 WHERE c.parent=pc.id AND c.depth=0 AND pc.depth=?";
63 if ($rs = $DB->get_recordset_sql($sql, array($parentdepth))) {
f33e1ed4 64 foreach ($rs as $cat) {
863850d2 65 $cat->depth = $parentdepth+1;
66 $cat->path = $cat->path.'/'.$cat->id;
f33e1ed4 67 $DB->update_record('course_categories', $cat);
863850d2 68 }
f33e1ed4 69 $rs->close();
863850d2 70 }
71 $parentdepth++;
72 if ($parentdepth > 100) {
73 //something must have gone wrong - nobody can have more than 100 levels of categories, right?
74 debugging('Unknown error fixing category depths');
75 break;
76 }
77 }
863850d2 78}
79
172dd12c 80/**
81 * Moves all course files except the moddata to new file storage
82 *
83 * Unfortunately this function uses core file related functions - it might be necessary to tweak it if something changes there :-(
84 */
85function upgrade_migrate_files_courses() {
86 global $DB, $CFG;
87 require_once($CFG->libdir.'/filelib.php');
88
d0b6f92a
PS
89 set_config('upgradenewfilemirgation', 1);
90
172dd12c 91 $count = $DB->count_records('course');
92 $pbar = new progress_bar('migratecoursefiles', 500, true);
93
94 $rs = $DB->get_recordset('course');
172dd12c 95 $i = 0;
96 foreach ($rs as $course) {
97 $i++;
775f811a 98 upgrade_set_timeout(60*5); // set up timeout, may also abort execution
172dd12c 99 $context = get_context_instance(CONTEXT_COURSE, $course->id);
100 upgrade_migrate_files_course($context, '/', true);
101 $pbar->update($i, $count, "Migrated course files - course $i/$count.");
102 }
172dd12c 103 $rs->close();
104
105 return true;
106}
107
d0b6f92a
PS
108/**
109 * Moodle 2.0dev was using xx/xx/xx file pool directory structure, this migrates the existing files to xx/xx.
110 * This will not be executed in production upgrades...
111 * @return void
112 */
113function upgrade_simplify_overkill_pool_structure() {
114 global $CFG, $OUTPUT;
115
116 if (isset($CFG->upgradenewfilemirgation)) {
117 // newer upgrade, directory structure is in the form xx/xx already
118 unset_config('upgradenewfilemirgation');
119 return;
120 }
121
122 $filedir = $CFG->dataroot.'/filedir'; // hardcoded hack, do not use elsewhere!!
123
124 echo $OUTPUT->notification("Changing file pool directory structure, this may take a while...", 'notifysuccess');
125
126 $dir_l1 = new DirectoryIterator($filedir);
127 foreach ($dir_l1 as $d1) {
128 if ($d1->isDot() or $d1->isLink() or !$d1->isDir()) {
129 continue;
130 }
131 $name1 = $d1->getFilename();
132 if (strlen($name1) != 2) {
133 continue; //weird
134 }
135 $dir_l2 = new DirectoryIterator("$filedir/$name1");
136 foreach ($dir_l2 as $d2) {
137 if ($d2->isDot() or $d2->isLink() or !$d2->isDir()) {
138 continue;
139 }
140 $name2 = $d2->getFilename();
141 if (strlen($name2) != 2) {
142 continue; //weird
143 }
144 $dir_l3 = new DirectoryIterator("$filedir/$name1/$name2");
145 foreach ($dir_l3 as $d3) {
146 if ($d3->isDot() or $d3->isLink() or !$d3->isDir()) {
147 continue;
148 }
149 $name3 = $d3->getFilename();
150 if (strlen($name3) != 2) {
151 continue; //weird
152 }
153 $dir_l4 = new DirectoryIterator("$filedir/$name1/$name2/$name3");
154 foreach ($dir_l4 as $d4) {
155 if (!$d4->isFile()) {
156 continue; //. or ..
157 }
158 upgrade_set_timeout(60*5); // set up timeout, may also abort execution
159 $newfile = "$filedir/$name1/$name2/".$d4->getFilename();
160 $oldfile = "$filedir/$name1/$name2/$name3/".$d4->getFilename();
161 if (!file_exists($newfile)) {
162 rename($oldfile, $newfile);
163 }
164 }
165 unset($d4);
166 unset($dir_l4);
167 rmdir("$filedir/$name1/$name2/$name3");
168 }
169 unset($d3);
170 unset($dir_l3); // release file handles
171 }
172 unset($d2);
173 unset($dir_l2); // release file handles
174 }
175}
176
edfd6a5e
PS
177/**
178 * Internal function - do not use directly
179 */
180function upgrade_migrate_user_icons() {
181 global $CFG, $OUTPUT, $DB;
182
183 $fs = get_file_storage();
184
185 $icon = array('component'=>'user', 'filearea'=>'icon', 'itemid'=>0, 'filepath'=>'/');
186
187 $count = $DB->count_records('user', array('picture'=>1, 'deleted'=>0));
188 $pbar = new progress_bar('migratecoursefiles', 500, true);
189
190 $rs = $DB->get_recordset('user', array('picture'=>1, 'deleted'=>0), 'id ASC', 'id, picture');
191 $i = 0;
192 foreach ($rs as $user) {
193 $i++;
194 upgrade_set_timeout(60); /// Give upgrade at least 60 more seconds
e88dd876 195 $pbar->update($i, $count, "Migrated user icons $i/$count.");
edfd6a5e
PS
196
197 $context = get_context_instance(CONTEXT_USER, $user->id);
198
199 if ($fs->file_exists($context->id, 'user', 'icon', 0, '/', 'f1.jpg')) {
200 // already converted!
201 continue;
202 }
203
204 $level1 = floor($user->id / 1000) * 1000;
205 $userdir = "$CFG->dataroot/user/$level1/$user->id";
206 if (!file_exists("$userdir/f1.jpg") or !file_exists("$userdir/f2.jpg")) {
207 $userdir = "$CFG->dataroot/users/$user->id";
208 if (!file_exists("$userdir/f1.jpg") or !file_exists("$userdir/f2.jpg")) {
209 // no image found, sorry
210 $user->picture = 0;
211 $DB->update_record('user', $user);
212 continue;
213 }
214 }
215
216 $icon['contextid'] = $context->id;
217 $icon['filename'] = 'f1.jpg';
218 $fs->create_file_from_pathname($icon, "$userdir/f1.jpg");
219 $icon['filename'] = 'f2.jpg';
220 $fs->create_file_from_pathname($icon, "$userdir/f2.jpg");
221 }
222 $rs->close();
223
224 // purge all old user image dirs
c7744f12
PS
225 remove_dir("$CFG->dataroot/user");
226 remove_dir("$CFG->dataroot/users");
edfd6a5e
PS
227}
228
e88dd876
PS
229/**
230 * Internal function - do not use directly
231 */
232function upgrade_migrate_group_icons() {
233 global $CFG, $OUTPUT, $DB;
234
235 $fs = get_file_storage();
236
237 $icon = array('component'=>'group', 'filearea'=>'icon', 'filepath'=>'/');
238
239 $count = $DB->count_records('groups', array('picture'=>1));
240 $pbar = new progress_bar('migrategroupfiles', 500, true);
241
242 $rs = $DB->get_recordset('groups', array('picture'=>1), 'courseid ASC', 'id, picture, courseid');
243 $i = 0;
244 foreach ($rs as $group) {
245 $i++;
246 upgrade_set_timeout(60); /// Give upgrade at least 60 more seconds
247 $pbar->update($i, $count, "Migrated group icons $i/$count.");
248
249 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
250
251 if ($fs->file_exists($context->id, 'group', 'icon', $group->id, '/', 'f1.jpg')) {
252 // already converted!
253 continue;
254 }
255
256 $groupdir = "$CFG->dataroot/groups/$group->id";
257 if (!file_exists("$groupdir/f1.jpg") or !file_exists("$groupdir/f2.jpg")) {
258 // no image found, sorry
259 $group->picture = 0;
260 $DB->update_record('groups', $group);
261 continue;
262 }
263
264 $icon['contextid'] = $context->id;
265 $icon['itemid'] = $group->id;
266 $icon['filename'] = 'f1.jpg';
267 $fs->create_file_from_pathname($icon, "$groupdir/f1.jpg");
268 $icon['filename'] = 'f2.jpg';
269 $fs->create_file_from_pathname($icon, "$groupdir/f2.jpg");
270 }
271 $rs->close();
272
273 // purge all old group image dirs
274 remove_dir("$CFG->dataroot/groups");
275}
276
172dd12c 277/**
278 * Internal function - do not use directly
279 */
280function upgrade_migrate_files_course($context, $path, $delete) {
aa9a6867 281 global $CFG, $OUTPUT;
172dd12c 282
283 $fullpathname = $CFG->dataroot.'/'.$context->instanceid.$path;
284 if (!file_exists($fullpathname)) {
285 return;
286 }
287 $items = new DirectoryIterator($fullpathname);
288 $fs = get_file_storage();
289
d217b950
PS
290 $textlib = textlib_get_instance();
291
172dd12c 292 foreach ($items as $item) {
293 if ($item->isDot()) {
294 continue;
295 }
296
297 if ($item->isLink()) {
775f811a 298 // do not delete symbolic links or its children
172dd12c 299 $delete_this = false;
300 } else {
301 $delete_this = $delete;
302 }
303
304 if (strpos($path, '/backupdata/') === 0) {
64f93798
PS
305 $component = 'backup';
306 $filearea = 'course';
307 $filepath = substr($path, strlen('/backupdata'));
172dd12c 308 } else {
64f93798
PS
309 $component = 'course';
310 $filearea = 'legacy';
311 $filepath = $path;
172dd12c 312 }
313
314 if ($item->isFile()) {
315 if (!$item->isReadable()) {
aa9a6867 316 echo $OUTPUT->notification(" File not readable, skipping: ".$fullpathname.$item->getFilename());
172dd12c 317 continue;
318 }
319
320 $filepath = clean_param($filepath, PARAM_PATH);
321 $filename = clean_param($item->getFilename(), PARAM_FILE);
322
323 if ($filename === '') {
aa54ed7b 324 //unsupported chars, sorry
172dd12c 325 continue;
326 }
327
0ed7146b 328 if ($textlib->strlen($filepath) > 255) {
d217b950
PS
329 echo $OUTPUT->notification(" File path longer than 255 chars, skipping: ".$fullpathname.$item->getFilename());
330 continue;
331 }
332
64f93798
PS
333 if (!$fs->file_exists($context->id, $component, $filearea, '0', $filepath, $filename)) {
334 $file_record = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename,
172dd12c 335 'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime());
336 if ($fs->create_file_from_pathname($file_record, $fullpathname.$item->getFilename())) {
337 if ($delete_this) {
338 @unlink($fullpathname.$item->getFilename());
339 }
340 }
341 }
342
343 } else {
344 if ($path == '/' and $item->getFilename() == 'moddata') {
345 continue; // modules are responsible
346 }
347
aa54ed7b 348 $dirname = clean_param($item->getFilename(), PARAM_PATH);
349 if ($dirname === '') {
350 //unsupported chars, sorry
351 continue;
352 }
353 $filepath = ($filepath.$dirname.'/');
172dd12c 354 if ($filepath !== '/backupdata/') {
64f93798 355 $fs->create_directory($context->id, $component, $filearea, 0, $filepath);
172dd12c 356 }
357
358 //migrate recursively all subdirectories
359 upgrade_migrate_files_course($context, $path.$item->getFilename().'/', $delete_this);
360 if ($delete_this) {
361 // delete dir if empty
362 @rmdir($fullpathname.$item->getFilename());
363 }
364 }
365 }
366 unset($items); //release file handles
367}
368
369/**
370 * Moves all block attachments
371 *
372 * Unfortunately this function uses core file related functions - it might be necessary to tweak it if something changes there :-(
373 */
374function upgrade_migrate_files_blog() {
aa9a6867 375 global $DB, $CFG, $OUTPUT;
172dd12c 376
377 $fs = get_file_storage();
378
a1442d4e 379 $count = $DB->count_records_select('post', "module='blog' AND attachment IS NOT NULL AND attachment <> '1'");
172dd12c 380
a1442d4e 381 if ($rs = $DB->get_recordset_select('post', "module='blog' AND attachment IS NOT NULL AND attachment <> '1'")) {
172dd12c 382
775f811a 383 upgrade_set_timeout(60*20); // set up timeout, may also abort execution
384
172dd12c 385 $pbar = new progress_bar('migrateblogfiles', 500, true);
386
172dd12c 387 $i = 0;
388 foreach ($rs as $entry) {
389 $i++;
390 $pathname = "$CFG->dataroot/blog/attachments/$entry->id/$entry->attachment";
391 if (!file_exists($pathname)) {
775f811a 392 $entry->attachment = NULL;
393 $DB->update_record('post', $entry);
172dd12c 394 continue;
395 }
396
397 $filename = clean_param($entry->attachment, PARAM_FILE);
398 if ($filename === '') {
399 // weird file name, ignore it
400 $entry->attachment = NULL;
401 $DB->update_record('post', $entry);
402 continue;
403 }
404
405 if (!is_readable($pathname)) {
aa9a6867 406 echo $OUTPUT->notification(" File not readable, skipping: ".$pathname);
172dd12c 407 continue;
408 }
409
64f93798
PS
410 if (!$fs->file_exists(SYSCONTEXTID, 'blog', 'attachment', $entry->id, '/', $filename)) {
411 $file_record = array('contextid'=>SYSCONTEXTID, 'component'=>'blog', 'filearea'=>'attachment', 'itemid'=>$entry->id, 'filepath'=>'/', 'filename'=>$filename,
775f811a 412 'timecreated'=>filectime($pathname), 'timemodified'=>filemtime($pathname), 'userid'=>$entry->userid);
172dd12c 413 $fs->create_file_from_pathname($file_record, $pathname);
414 }
415 @unlink($pathname);
416 @rmdir("$CFG->dataroot/blog/attachments/$entry->id/");
417
418 $entry->attachment = 1; // file name not needed there anymore
419 $DB->update_record('post', $entry);
420 $pbar->update($i, $count, "Migrated blog attachments - $i/$count.");
421 }
172dd12c 422 $rs->close();
423 }
775f811a 424
172dd12c 425 @rmdir("$CFG->dataroot/blog/attachments/");
426 @rmdir("$CFG->dataroot/blog/");
427}
02caf1e7 428
429/**
430 * This function will fix the status of the localhost/all records in the mnet_host table
431 * checking they exist and adding them if missing + redefine CFG->mnet_localhost_id and
432 * CFG->mnet_all_hosts_id if needed + update all the users having non-existent mnethostid
433 * to correct CFG->mnet_localhost_id
434 *
435 * Implemented because, at some point, specially in old installations upgraded along
436 * multiple versions, sometimes the stuff above has ended being inconsistent, causing
c0002023 437 * problems here and there (noticeably in backup/restore). MDL-16879
02caf1e7 438 */
439function upgrade_fix_incorrect_mnethostids() {
440
441 global $CFG, $DB;
442
443/// Get current $CFG/mnet_host records
444 $old_mnet_localhost_id = !empty($CFG->mnet_localhost_id) ? $CFG->mnet_localhost_id : 0;
445 $old_mnet_all_hosts_id = !empty($CFG->mnet_all_hosts_id) ? $CFG->mnet_all_hosts_id : 0;
446
447 $current_mnet_localhost_host = $DB->get_record('mnet_host', array('wwwroot' => $CFG->wwwroot)); /// By wwwroot
448 $current_mnet_all_hosts_host = $DB->get_record_select('mnet_host', $DB->sql_isempty('mnet_host', 'wwwroot', false, false)); /// By empty wwwroot
449
7062a798
PL
450 if (!$moodleapplicationid = $DB->get_field('mnet_application', 'id', array('name' => 'moodle'))) {
451 $m = (object)array(
452 'name' => 'moodle',
453 'display_name' => 'Moodle',
454 'xmlrpc_server_url' => '/mnet/xmlrpc/server.php',
455 'sso_land_url' => '/auth/mnet/land.php',
c9606565 456 'sso_jump_url' => '/auth/mnet/jump.php',
7062a798
PL
457 );
458 $moodleapplicationid = $DB->insert_record('mnet_application', $m);
459 }
460
02caf1e7 461/// Create localhost_host if necessary (pretty improbable but better to be 100% in the safe side)
462/// Code stolen from mnet_environment->init
463 if (!$current_mnet_localhost_host) {
464 $current_mnet_localhost_host = new stdClass();
465 $current_mnet_localhost_host->wwwroot = $CFG->wwwroot;
466 $current_mnet_localhost_host->ip_address = '';
467 $current_mnet_localhost_host->public_key = '';
468 $current_mnet_localhost_host->public_key_expires = 0;
469 $current_mnet_localhost_host->last_connect_time = 0;
470 $current_mnet_localhost_host->last_log_id = 0;
471 $current_mnet_localhost_host->deleted = 0;
472 $current_mnet_localhost_host->name = '';
7062a798 473 $current_mnet_localhost_host->applicationid = $moodleapplicationid;
02caf1e7 474 /// Get the ip of the server
475 if (empty($_SERVER['SERVER_ADDR'])) {
476 /// SERVER_ADDR is only returned by Apache-like webservers
477 $count = preg_match("@^(?:http[s]?://)?([A-Z0-9\-\.]+).*@i", $current_mnet_localhost_host->wwwroot, $matches);
478 $my_hostname = $count > 0 ? $matches[1] : false;
479 $my_ip = gethostbyname($my_hostname); // Returns unmodified hostname on failure. DOH!
480 if ($my_ip == $my_hostname) {
481 $current_mnet_localhost_host->ip_address = 'UNKNOWN';
482 } else {
483 $current_mnet_localhost_host->ip_address = $my_ip;
484 }
485 } else {
486 $current_mnet_localhost_host->ip_address = $_SERVER['SERVER_ADDR'];
487 }
488 $current_mnet_localhost_host->id = $DB->insert_record('mnet_host', $current_mnet_localhost_host, true);
489 }
490
491/// Create all_hosts_host if necessary (pretty improbable but better to be 100% in the safe side)
492/// Code stolen from mnet_environment->init
493 if (!$current_mnet_all_hosts_host) {
494 $current_mnet_all_hosts_host = new stdClass();
495 $current_mnet_all_hosts_host->wwwroot = '';
496 $current_mnet_all_hosts_host->ip_address = '';
497 $current_mnet_all_hosts_host->public_key = '';
498 $current_mnet_all_hosts_host->public_key_expires = 0;
499 $current_mnet_all_hosts_host->last_connect_time = 0;
500 $current_mnet_all_hosts_host->last_log_id = 0;
501 $current_mnet_all_hosts_host->deleted = 0;
502 $current_mnet_all_hosts_host->name = 'All Hosts';
7062a798 503 $current_mnet_all_hosts_host->applicationid = $moodleapplicationid;
02caf1e7 504 $current_mnet_all_hosts_host->id = $DB->insert_record('mnet_host', $current_mnet_all_hosts_host, true);
505 }
506
507/// Compare old_mnet_localhost_id and current_mnet_localhost_host
508
509 if ($old_mnet_localhost_id != $current_mnet_localhost_host->id) { /// Different = problems
510 /// Update $CFG->mnet_localhost_id to correct value
511 set_config('mnet_localhost_id', $current_mnet_localhost_host->id);
512
513 /// Delete $old_mnet_localhost_id if exists (users will be assigned to new one below)
514 $DB->delete_records('mnet_host', array('id' => $old_mnet_localhost_id));
515 }
516
517/// Compare old_mnet_all_hosts_id and current_mnet_all_hosts_host
518
519 if ($old_mnet_all_hosts_id != $current_mnet_all_hosts_host->id) { /// Different = problems
520 /// Update $CFG->mnet_localhost_id to correct value
521 set_config('mnet_all_hosts_id', $current_mnet_all_hosts_host->id);
522
523 /// Delete $old_mnet_all_hosts_id if exists
524 $DB->delete_records('mnet_host', array('id' => $old_mnet_all_hosts_id));
525 }
526
527/// Finally, update all the incorrect user->mnethostid to the correct CFG->mnet_localhost_id, preventing UIX dupes
528 $hosts = $DB->get_records_menu('mnet_host', null, '', 'id, id AS id2');
529 list($in_sql, $in_params) = $DB->get_in_or_equal($hosts, SQL_PARAMS_QM, null, false);
530
531 $sql = "SELECT id
ba73136e 532 FROM {user} u1
02caf1e7 533 WHERE u1.mnethostid $in_sql
534 AND NOT EXISTS (
535 SELECT 'x'
ba73136e 536 FROM {user} u2
02caf1e7 537 WHERE u2.username = u1.username
538 AND u2.mnethostid = ?)";
539
540 $params = array_merge($in_params, array($current_mnet_localhost_host->id));
541
542 if ($rs = $DB->get_recordset_sql($sql, $params)) {
543 foreach ($rs as $rec) {
544 $DB->set_field('user', 'mnethostid', $current_mnet_localhost_host->id, array('id' => $rec->id));
545 upgrade_set_timeout(60); /// Give upgrade at least 60 more seconds
546 }
547 $rs->close();
548 }
7062a798
PL
549
550 // fix up any host records that have incorrect ids
551 $DB->set_field_select('mnet_host', 'applicationid', $moodleapplicationid, 'id = ? or id = ?', array($current_mnet_localhost_host->id, $current_mnet_all_hosts_host->id));
552
02caf1e7 553}
554
7d2a0492 555/**
556 * This function is used as part of the great navigation upgrade of 20090828
557 * It is used to clean up contexts that are unique to a blocks that are about
558 * to be removed.
559 *
560 *
561 * Look at {@link blocklib.php::blocks_delete_instance()} the function from
562 * which I based this code. It is important to mention one very important fact
563 * before doing this I checked that the blocks did not override the
564 * {@link block_base::instance_delete()} method. Should this function ever
565 * be repeated check this again
117bd748 566 *
7d2a0492 567 * @link lib/db/upgrade.php
568 *
569 * @since navigation upgrade 20090828
570 * @param array $contextidarray An array of block instance context ids
61676608 571 * @return void
7d2a0492 572 */
573function upgrade_cleanup_unwanted_block_contexts($contextidarray) {
574 global $DB;
575
576 if (!is_array($contextidarray) || count($contextidarray)===0) {
577 // Ummmm no instances?
61676608 578 return;
7d2a0492 579 }
580
581 $contextidstring = join(',', $contextidarray);
582
583 $blockcontexts = $DB->get_recordset_select('context', 'contextlevel = '.CONTEXT_BLOCK.' AND id IN ('.$contextidstring.')', array(), '', 'id, contextlevel');
584 $blockcontextids = array();
585 foreach ($blockcontexts as $blockcontext) {
586 $blockcontextids[] = $blockcontext->id;
587 }
588
589 if (count($blockcontextids)===0) {
590 // None of the instances have unique contexts
61676608 591 return;
7d2a0492 592 }
593
594 $blockcontextidsstring = join(',', $blockcontextids);
595
61676608
PS
596 $DB->delete_records_select('role_assignments', 'contextid IN ('.$blockcontextidsstring.')');
597 $DB->delete_records_select('role_capabilities', 'contextid IN ('.$blockcontextidsstring.')');
598 $DB->delete_records_select('role_names', 'contextid IN ('.$blockcontextidsstring.')');
599 $DB->delete_records_select('context', 'id IN ('.$blockcontextidsstring.')');
67e4713c 600}