From 1405f010b7c52026f2838647bd8adf6734fc8a9e Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 8 Feb 2016 00:23:01 +0100 Subject: [PATCH] MDL-51580 upgradelib: Delete stuff used by removed upgrade steps This commits removes stuff from different upgradelib files, used exclusively by the already deleted upgrade steps. Given such exclusivity it was not needed to proceed with a 2-phase deprecation as far as the functions were 100% internal to upgrade. This is the list of deleted functions, all them docummented in their corresponding upgrade.txt files: - repository_picasa_admin_upgrade_notification(); - repository_googledocs_admin_upgrade_notification(); - repository_boxnet_admin_upgrade_notification(); - repository_alfresco_admin_security_key_notice(); - qtype_essay_convert_to_html(); - portfolio_picasa_admin_upgrade_notification(); - portfolio_googledocs_admin_upgrade_notification(); - portfolio_boxnet_admin_upgrade_notification(); - mod_book_migrate_moddata_dir_to_legacy(); - mod_book_migrate_all_areas(); - mod_book_migrate_area(); - mod_assignment_pending_upgrades_notification(); - upgrade_mysql_fix_unsigned_and_lob_columns(); - upgrade_course_completion_remove_duplicates(); - upgrade_save_orphaned_questions(); - upgrade_rename_old_backup_files_using_shortname(); - upgrade_mssql_nvarcharmax(); - upgrade_mssql_varbinarymax(); - upgrade_fix_missing_root_folders(); - upgrade_course_modules_sequences(); - upgrade_grade_item_fix_sortorder(); - upgrade_availability_item(); --- lib/db/upgradelib.php | 381 ------------------------ lib/tests/upgradelib_test.php | 247 +-------------- lib/upgrade.txt | 13 + lib/upgradelib.php | 294 ------------------ mod/assignment/db/upgradelib.php | 54 ---- mod/book/db/upgradelib.php | 172 ----------- mod/book/upgrade.txt | 10 +- portfolio/boxnet/db/upgradelib.php | 55 ---- portfolio/googledocs/db/upgradelib.php | 53 ---- portfolio/picasa/db/upgradelib.php | 53 ---- portfolio/upgrade.txt | 8 + question/type/upgrade.txt | 6 + repository/alfresco/db/upgradelib.php | 53 ---- repository/boxnet/db/upgradelib.php | 55 ---- repository/googledocs/db/upgradelib.php | 53 ---- repository/picasa/db/upgradelib.php | 53 ---- repository/upgrade.txt | 9 + 17 files changed, 57 insertions(+), 1512 deletions(-) delete mode 100644 mod/assignment/db/upgradelib.php delete mode 100644 mod/book/db/upgradelib.php delete mode 100644 portfolio/boxnet/db/upgradelib.php delete mode 100644 portfolio/googledocs/db/upgradelib.php delete mode 100644 portfolio/picasa/db/upgradelib.php delete mode 100644 repository/alfresco/db/upgradelib.php delete mode 100644 repository/boxnet/db/upgradelib.php delete mode 100644 repository/googledocs/db/upgradelib.php delete mode 100644 repository/picasa/db/upgradelib.php diff --git a/lib/db/upgradelib.php b/lib/db/upgradelib.php index 5b0c83884a880..e6b29abcf65d8 100644 --- a/lib/db/upgradelib.php +++ b/lib/db/upgradelib.php @@ -76,387 +76,6 @@ function upgrade_mysql_get_supported_tables() { return $tables; } -/** - * Remove all signed numbers from current database and change - * text fields to long texts - mysql only. - */ -function upgrade_mysql_fix_unsigned_and_lob_columns() { - // We are not using standard API for changes of column - // because everything 'signed'-related will be removed soon. - - // If anybody already has numbers higher than signed limit the execution stops - // and tables must be fixed manually before continuing upgrade. - - global $DB; - - if ($DB->get_dbfamily() !== 'mysql') { - return; - } - - $pbar = new progress_bar('mysqlconvertunsignedlobs', 500, true); - - $prefix = $DB->get_prefix(); - $tables = upgrade_mysql_get_supported_tables(); - - $tablecount = count($tables); - $i = 0; - foreach ($tables as $table) { - $i++; - - $changes = array(); - - $sql = "SHOW COLUMNS FROM `{{$table}}`"; - $rs = $DB->get_recordset_sql($sql); - foreach ($rs as $column) { - $column = (object)array_change_key_case((array)$column, CASE_LOWER); - if (stripos($column->type, 'unsigned') !== false) { - $maxvalue = 0; - if (preg_match('/^int/i', $column->type)) { - $maxvalue = 2147483647; - } else if (preg_match('/^medium/i', $column->type)) { - $maxvalue = 8388607; - } else if (preg_match('/^smallint/i', $column->type)) { - $maxvalue = 32767; - } else if (preg_match('/^tinyint/i', $column->type)) { - $maxvalue = 127; - } - if ($maxvalue) { - // Make sure nobody is abusing our integer ranges - moodle int sizes are in digits, not bytes!!! - $invalidcount = $DB->get_field_sql("SELECT COUNT('x') FROM `{{$table}}` WHERE `$column->field` > :maxnumber", array('maxnumber'=>$maxvalue)); - if ($invalidcount) { - throw new moodle_exception('notlocalisederrormessage', 'error', new moodle_url('/admin/'), "Database table '{$table}'' contains unsigned column '{$column->field}' with $invalidcount values that are out of allowed range, upgrade can not continue."); - } - } - $type = preg_replace('/unsigned/i', 'signed', $column->type); - $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL'; - $default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : ''; - $autoinc = (stripos($column->extra, 'auto_increment') !== false) ? 'AUTO_INCREMENT' : ''; - // Primary and unique not necessary here, change_database_structure does not add prefix. - $changes[] = "MODIFY COLUMN `$column->field` $type $notnull $default $autoinc"; - - } else if ($column->type === 'tinytext' or $column->type === 'mediumtext' or $column->type === 'text') { - $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL'; - $default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : ''; - // Primary, unique and inc are not supported for texts. - $changes[] = "MODIFY COLUMN `$column->field` LONGTEXT $notnull $default"; - - } else if ($column->type === 'tinyblob' or $column->type === 'mediumblob' or $column->type === 'blob') { - $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL'; - $default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : ''; - // Primary, unique and inc are not supported for blobs. - $changes[] = "MODIFY COLUMN `$column->field` LONGBLOB $notnull $default"; - } - - } - $rs->close(); - - if ($changes) { - // Set appropriate timeout - 1 minute per thousand of records should be enough, min 60 minutes just in case. - $count = $DB->count_records($table, array()); - $timeout = ($count/1000)*60; - $timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout; - upgrade_set_timeout($timeout); - - $sql = "ALTER TABLE `{$prefix}$table` ".implode(', ', $changes); - $DB->change_database_structure($sql); - } - - $pbar->update($i, $tablecount, "Converted unsigned/lob columns in MySQL database - $i/$tablecount."); - } -} - -/** - * Migrate NTEXT to NVARCHAR(MAX). - */ -function upgrade_mssql_nvarcharmax() { - global $DB; - - if ($DB->get_dbfamily() !== 'mssql') { - return; - } - - $pbar = new progress_bar('mssqlconvertntext', 500, true); - - $prefix = $DB->get_prefix(); - $tables = $DB->get_tables(false); - - $tablecount = count($tables); - $i = 0; - foreach ($tables as $table) { - $i++; - - $columns = array(); - - $sql = "SELECT column_name - FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = '{{$table}}' AND UPPER(data_type) = 'NTEXT'"; - $rs = $DB->get_recordset_sql($sql); - foreach ($rs as $column) { - $columns[] = $column->column_name; - } - $rs->close(); - - if ($columns) { - // Set appropriate timeout - 1 minute per thousand of records should be enough, min 60 minutes just in case. - $count = $DB->count_records($table, array()); - $timeout = ($count/1000)*60; - $timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout; - upgrade_set_timeout($timeout); - - $updates = array(); - foreach ($columns as $column) { - // Change the definition. - $sql = "ALTER TABLE {$prefix}$table ALTER COLUMN $column NVARCHAR(MAX)"; - $DB->change_database_structure($sql); - $updates[] = "$column = $column"; - } - - // Now force the migration of text data to new optimised storage. - $sql = "UPDATE {{$table}} SET ".implode(', ', $updates); - $DB->execute($sql); - } - - $pbar->update($i, $tablecount, "Converted NTEXT to NVARCHAR(MAX) columns in MS SQL Server database - $i/$tablecount."); - } -} - -/** - * Migrate IMAGE to VARBINARY(MAX). - */ -function upgrade_mssql_varbinarymax() { - global $DB; - - if ($DB->get_dbfamily() !== 'mssql') { - return; - } - - $pbar = new progress_bar('mssqlconvertimage', 500, true); - - $prefix = $DB->get_prefix(); - $tables = $DB->get_tables(false); - - $tablecount = count($tables); - $i = 0; - foreach ($tables as $table) { - $i++; - - $columns = array(); - - $sql = "SELECT column_name - FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = '{{$table}}' AND UPPER(data_type) = 'IMAGE'"; - $rs = $DB->get_recordset_sql($sql); - foreach ($rs as $column) { - $columns[] = $column->column_name; - } - $rs->close(); - - if ($columns) { - // Set appropriate timeout - 1 minute per thousand of records should be enough, min 60 minutes just in case. - $count = $DB->count_records($table, array()); - $timeout = ($count/1000)*60; - $timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout; - upgrade_set_timeout($timeout); - - foreach ($columns as $column) { - // Change the definition. - $sql = "ALTER TABLE {$prefix}$table ALTER COLUMN $column VARBINARY(MAX)"; - $DB->change_database_structure($sql); - } - - // Binary columns should not be used, do not waste time optimising the storage. - } - - $pbar->update($i, $tablecount, "Converted IMAGE to VARBINARY(MAX) columns in MS SQL Server database - $i/$tablecount."); - } -} - -/** - * This upgrade script fixes the mismatches between DB fields course_modules.section - * and course_sections.sequence. It makes sure that each module is included - * in the sequence of at least one section. - * Note that this script is different from admin/cli/fix_course_sortorder.php - * in the following ways: - * 1. It does not fix the cases when module appears several times in section(s) sequence(s) - - * it will be done automatically on the next viewing of the course. - * 2. It does not remove non-existing modules from section sequences - administrator - * has to run the CLI script to do it. - * 3. When this script finds an orphaned module it adds it to the section but makes hidden - * where CLI script does not change the visiblity specified in the course_modules table. - */ -function upgrade_course_modules_sequences() { - global $DB; - - // Find all modules that point to the section which does not point back to this module. - $sequenceconcat = $DB->sql_concat("','", "s.sequence", "','"); - $moduleconcat = $DB->sql_concat("'%,'", "m.id", "',%'"); - $sql = "SELECT m.id, m.course, m.section, s.sequence - FROM {course_modules} m LEFT OUTER JOIN {course_sections} s - ON m.course = s.course and m.section = s.id - WHERE s.sequence IS NULL OR ($sequenceconcat NOT LIKE $moduleconcat) - ORDER BY m.course"; - $rs = $DB->get_recordset_sql($sql); - $sections = null; - foreach ($rs as $cm) { - if (!isset($sections[$cm->course])) { - // Retrieve all sections for the course (only once for each corrupt course). - $sections = array($cm->course => - $DB->get_records('course_sections', array('course' => $cm->course), - 'section', 'id, section, sequence, visible')); - if (empty($sections[$cm->course])) { - // Very odd - the course has a module in it but has no sections. Create 0-section. - $newsection = array('sequence' => '', 'section' => 0, 'visible' => 1); - $newsection['id'] = $DB->insert_record('course_sections', - $newsection + array('course' => $cm->course, 'summary' => '', 'summaryformat' => FORMAT_HTML)); - $sections[$cm->course] = array($newsection['id'] => (object)$newsection); - } - } - // Attempt to find the section that has this module in it's sequence. - // If there are several of them, pick the last because this is what get_fast_modinfo() does. - $sectionid = null; - foreach ($sections[$cm->course] as $section) { - if (!empty($section->sequence) && in_array($cm->id, preg_split('/,/', $section->sequence))) { - $sectionid = $section->id; - } - } - if ($sectionid) { - // Found the section. Update course_module to point to the correct section. - $params = array('id' => $cm->id, 'section' => $sectionid); - if (!$sections[$cm->course][$sectionid]->visible) { - $params['visible'] = 0; - } - $DB->update_record('course_modules', $params); - } else { - // No section in the course has this module in it's sequence. - if (isset($sections[$cm->course][$cm->section])) { - // Try to add module to the section it points to (if it is valid). - $sectionid = $cm->section; - } else { - // Section not found. Just add to the first available section. - reset($sections[$cm->course]); - $sectionid = key($sections[$cm->course]); - } - $newsequence = ltrim($sections[$cm->course][$sectionid]->sequence . ',' . $cm->id, ','); - $sections[$cm->course][$sectionid]->sequence = $newsequence; - $DB->update_record('course_sections', array('id' => $sectionid, 'sequence' => $newsequence)); - // Make module invisible because it was not displayed at all before this upgrade script. - $DB->update_record('course_modules', array('id' => $cm->id, 'section' => $sectionid, 'visible' => 0, 'visibleold' => 0)); - } - } - $rs->close(); - unset($sections); - - // Note that we don't need to reset course cache here because it is reset automatically after upgrade. -} - -/** - * Updates a single item (course module or course section) to transfer the - * availability settings from the old to the new format. - * - * Note: We do not convert groupmembersonly for modules at present. If we did, - * $groupmembersonly would be set to the groupmembersonly option for the - * module. Since we don't, it will be set to 0 for modules, and 1 for sections - * if they have a grouping. - * - * @param int $groupmembersonly 1 if activity has groupmembersonly option - * @param int $groupingid Grouping id (0 = none) - * @param int $availablefrom Available from time (0 = none) - * @param int $availableuntil Available until time (0 = none) - * @param int $showavailability Show availability (1) or hide activity entirely - * @param array $availrecs Records from course_modules/sections_availability - * @param array $fieldrecs Records from course_modules/sections_avail_fields - */ -function upgrade_availability_item($groupmembersonly, $groupingid, - $availablefrom, $availableuntil, $showavailability, - array $availrecs, array $fieldrecs) { - global $CFG, $DB; - $conditions = array(); - $shows = array(); - - // Group members only condition (if enabled). - if ($CFG->enablegroupmembersonly && $groupmembersonly) { - if ($groupingid) { - $conditions[] = '{"type":"grouping"' . - ($groupingid ? ',"id":' . $groupingid : '') . '}'; - } else { - // No grouping specified, so allow any group. - $conditions[] = '{"type":"group"}'; - } - // Group members only condition was not displayed to students. - $shows[] = 'false'; - - // In the unlikely event that the site had enablegroupmembers only - // but NOT enableavailability, we need to turn this on now. - if (!$CFG->enableavailability) { - set_config('enableavailability', 1); - } - } - - // Date conditions. - if ($availablefrom) { - $conditions[] = '{"type":"date","d":">=","t":' . $availablefrom . '}'; - $shows[] = $showavailability ? 'true' : 'false'; - } - if ($availableuntil) { - $conditions[] = '{"type":"date","d":"<","t":' . $availableuntil . '}'; - // Until dates never showed to students. - $shows[] = 'false'; - } - - // Conditions from _availability table. - foreach ($availrecs as $rec) { - if (!empty($rec->sourcecmid)) { - // Completion condition. - $conditions[] = '{"type":"completion","cm":' . $rec->sourcecmid . - ',"e":' . $rec->requiredcompletion . '}'; - } else { - // Grade condition. - $minmax = ''; - if (!empty($rec->grademin)) { - $minmax .= ',"min":' . sprintf('%.5f', $rec->grademin); - } - if (!empty($rec->grademax)) { - $minmax .= ',"max":' . sprintf('%.5f', $rec->grademax); - } - $conditions[] = '{"type":"grade","id":' . $rec->gradeitemid . $minmax . '}'; - } - $shows[] = $showavailability ? 'true' : 'false'; - } - - // Conditions from _fields table. - foreach ($fieldrecs as $rec) { - if (isset($rec->userfield)) { - // Standard field. - $fieldbit = ',"sf":' . json_encode($rec->userfield); - } else { - // Custom field. - $fieldbit = ',"cf":' . json_encode($rec->shortname); - } - // Value is not included for certain operators. - switch($rec->operator) { - case 'isempty': - case 'isnotempty': - $valuebit = ''; - break; - - default: - $valuebit = ',"v":' . json_encode($rec->value); - break; - } - $conditions[] = '{"type":"profile","op":"' . $rec->operator . '"' . - $fieldbit . $valuebit . '}'; - $shows[] = $showavailability ? 'true' : 'false'; - } - - // If there are some conditions, set them into database. - if ($conditions) { - return '{"op":"&","showc":[' . implode(',', $shows) . '],' . - '"c":[' . implode(',', $conditions) . ']}'; - } else { - return null; - } -} - /** * Using data for a single course-module that has groupmembersonly enabled, * returns the new availability value that incorporates the correct diff --git a/lib/tests/upgradelib_test.php b/lib/tests/upgradelib_test.php index ca40f86439860..1c4b7073de0e8 100644 --- a/lib/tests/upgradelib_test.php +++ b/lib/tests/upgradelib_test.php @@ -43,80 +43,6 @@ public function test_upgrade_stale_php_files_present() { $this->assertFalse(upgrade_stale_php_files_present()); } - /** - * Test the {@link upgrade_grade_item_fix_sortorder() function with - * faked duplicate sortorder data. - */ - public function test_upgrade_grade_item_fix_sortorder() { - global $DB; - - $this->resetAfterTest(true); - - // The purpose of this test is to make sure that after upgrade script - // there is no duplicates in the field grade_items.sortorder (for each course) - // and the result of query "SELECT id FROM grade_items WHERE courseid=? ORDER BY sortorder, id" does not change. - $sequencesql = 'SELECT id FROM {grade_items} WHERE courseid=? ORDER BY sortorder, id'; - - // Each set is used for filling the db with fake data and will be representing the result of query: - // "SELECT sortorder from {grade_items} WHERE courseid=? ORDER BY id". - $testsets = array( - // Items that need no action. - array(1,2,3), - array(5,6,7), - array(7,6,1,3,2,5), - // Items with sortorder duplicates - array(1,2,2,3,3,4,5), - // Only one sortorder duplicate. - array(1,1), - array(3,3), - // Non-sequential sortorders with one or multiple duplicates. - array(3,3,7,5,6,6,9,10,8,3), - array(7,7,3), - array(3,4,5,3,5,4,7,1) - ); - $origsequences = array(); - - // Generate the data and remember the initial sequence or items. - foreach ($testsets as $testset) { - $course = $this->getDataGenerator()->create_course(); - foreach ($testset as $sortorder) { - $this->insert_fake_grade_item_sortorder($course->id, $sortorder); - } - $DB->get_records('grade_items'); - $origsequences[$course->id] = $DB->get_fieldset_sql($sequencesql, array($course->id)); - } - - $duplicatedetectionsql = "SELECT courseid, sortorder - FROM {grade_items} - GROUP BY courseid, sortorder - HAVING COUNT(id) > 1"; - - // Verify there are duplicates before we start the fix. - $dupes = $DB->record_exists_sql($duplicatedetectionsql); - $this->assertTrue($dupes); - - // Do the work. - upgrade_grade_item_fix_sortorder(); - - // Verify that no duplicates are left in the database. - $dupes = $DB->record_exists_sql($duplicatedetectionsql); - $this->assertFalse($dupes); - - // Verify that sequences are exactly the same as they were before upgrade script. - $idx = 0; - foreach ($origsequences as $courseid => $origsequence) { - if (count(($testsets[$idx])) == count(array_unique($testsets[$idx]))) { - // If there were no duplicates for this course verify that sortorders are not modified. - $newsortorders = $DB->get_fieldset_sql("SELECT sortorder from {grade_items} WHERE courseid=? ORDER BY id", array($courseid)); - $this->assertEquals($testsets[$idx], $newsortorders); - } - $newsequence = $DB->get_fieldset_sql($sequencesql, array($courseid)); - $this->assertEquals($origsequence, $newsequence, - "Sequences do not match for test set $idx : ".join(',', $testsets[$idx])); - $idx++; - } - } - /** * Populate some fake grade items into the database with specified * sortorder and course id. @@ -150,57 +76,6 @@ private function insert_fake_grade_item_sortorder($courseid, $sortorder) { return $DB->get_record('grade_items', array('id' => $item->id)); } - public function test_upgrade_fix_missing_root_folders() { - global $DB, $SITE; - - $this->resetAfterTest(true); - - // Setup some broken data... - // Create two resources (and associated file areas). - $this->setAdminUser(); - $resource1 = $this->getDataGenerator()->get_plugin_generator('mod_resource') - ->create_instance(array('course' => $SITE->id)); - $resource2 = $this->getDataGenerator()->get_plugin_generator('mod_resource') - ->create_instance(array('course' => $SITE->id)); - - // Delete the folder record of resource1 to simulate broken data. - $context = context_module::instance($resource1->cmid); - $selectargs = array('contextid' => $context->id, - 'component' => 'mod_resource', - 'filearea' => 'content', - 'itemid' => 0); - - // Verify file records exist. - $areafilecount = $DB->count_records('files', $selectargs); - $this->assertNotEmpty($areafilecount); - - // Delete the folder record. - $folderrecord = $selectargs; - $folderrecord['filepath'] = '/'; - $folderrecord['filename'] = '.'; - - // Get previous folder record. - $oldrecord = $DB->get_record('files', $folderrecord); - $DB->delete_records('files', $folderrecord); - - // Verify the folder record has been removed. - $newareafilecount = $DB->count_records('files', $selectargs); - $this->assertSame($newareafilecount, $areafilecount - 1); - - $this->assertFalse($DB->record_exists('files', $folderrecord)); - - // Run the upgrade step! - upgrade_fix_missing_root_folders(); - - // Verify the folder record has been restored. - $newareafilecount = $DB->count_records('files', $selectargs); - $this->assertSame($newareafilecount, $areafilecount); - - $newrecord = $DB->get_record('files', $folderrecord, '*', MUST_EXIST); - // Verify the hash is correctly created. - $this->assertSame($oldrecord->pathnamehash, $newrecord->pathnamehash); - } - public function test_upgrade_fix_missing_root_folders_draft() { global $DB, $SITE; @@ -245,115 +120,6 @@ public function test_upgrade_fix_missing_root_folders_draft() { $this->assertEquals($originalhash, $newhash); } - /** - * Tests the upgrade of an individual course-module or section from the - * old to new availability system. (This test does not use the database - * so it can run any time.) - */ - public function test_upgrade_availability_item() { - global $CFG; - $this->resetAfterTest(); - - // This function is in the other upgradelib. - require_once($CFG->libdir . '/db/upgradelib.php'); - - // Groupmembersonly (or nothing). Show option on but ignored. - // Note: This $CFG option doesn't exist any more but we are testing the - // upgrade function so it did exist then... - $CFG->enablegroupmembersonly = 0; - $this->assertNull( - upgrade_availability_item(1, 0, 0, 0, 1, array(), array())); - $CFG->enablegroupmembersonly = 1; - $this->assertNull( - upgrade_availability_item(0, 0, 0, 0, 1, array(), array())); - $this->assertEquals( - '{"op":"&","showc":[false],"c":[{"type":"group"}]}', - upgrade_availability_item(1, 0, 0, 0, 1, array(), array())); - $this->assertEquals( - '{"op":"&","showc":[false],"c":[{"type":"grouping","id":4}]}', - upgrade_availability_item(1, 4, 0, 0, 1, array(), array())); - - // Dates (with show/hide options - until date always hides). - $this->assertEquals( - '{"op":"&","showc":[true],"c":[{"type":"date","d":">=","t":996}]}', - upgrade_availability_item(0, 0, 996, 0, 1, array(), array())); - $this->assertEquals( - '{"op":"&","showc":[false],"c":[{"type":"date","d":">=","t":997}]}', - upgrade_availability_item(0, 0, 997, 0, 0, array(), array())); - $this->assertEquals( - '{"op":"&","showc":[false],"c":[{"type":"date","d":"<","t":998}]}', - upgrade_availability_item(0, 0, 0, 998, 1, array(), array())); - $this->assertEquals( - '{"op":"&","showc":[true,false],"c":[' . - '{"type":"date","d":">=","t":995},{"type":"date","d":"<","t":999}]}', - upgrade_availability_item(0, 0, 995, 999, 1, array(), array())); - - // Grade (show option works as normal). - $availrec = (object)array( - 'sourcecmid' => null, 'requiredcompletion' => null, - 'gradeitemid' => 13, 'grademin' => null, 'grademax' => null); - $this->assertEquals( - '{"op":"&","showc":[true],"c":[{"type":"grade","id":13}]}', - upgrade_availability_item(0, 0, 0, 0, 1, array($availrec), array())); - $availrec->grademin = 4.1; - $this->assertEquals( - '{"op":"&","showc":[false],"c":[{"type":"grade","id":13,"min":4.10000}]}', - upgrade_availability_item(0, 0, 0, 0, 0, array($availrec), array())); - $availrec->grademax = 9.9; - $this->assertEquals( - '{"op":"&","showc":[true],"c":[{"type":"grade","id":13,"min":4.10000,"max":9.90000}]}', - upgrade_availability_item(0, 0, 0, 0, 1, array($availrec), array())); - $availrec->grademin = null; - $this->assertEquals( - '{"op":"&","showc":[true],"c":[{"type":"grade","id":13,"max":9.90000}]}', - upgrade_availability_item(0, 0, 0, 0, 1, array($availrec), array())); - - // Completion (show option normal). - $availrec->grademax = null; - $availrec->gradeitemid = null; - $availrec->sourcecmid = 666; - $availrec->requiredcompletion = 1; - $this->assertEquals( - '{"op":"&","showc":[true],"c":[{"type":"completion","cm":666,"e":1}]}', - upgrade_availability_item(0, 0, 0, 0, 1, array($availrec), array())); - $this->assertEquals( - '{"op":"&","showc":[false],"c":[{"type":"completion","cm":666,"e":1}]}', - upgrade_availability_item(0, 0, 0, 0, 0, array($availrec), array())); - - // Profile conditions (custom/standard field, values/not, show option normal). - $fieldrec = (object)array('userfield' => 'email', 'operator' => 'isempty', - 'value' => '', 'shortname' => null); - $this->assertEquals( - '{"op":"&","showc":[true],"c":[{"type":"profile","op":"isempty","sf":"email"}]}', - upgrade_availability_item(0, 0, 0, 0, 1, array(), array($fieldrec))); - $fieldrec->value = '@'; - $fieldrec->operator = 'contains'; - $this->assertEquals( - '{"op":"&","showc":[true],"c":[{"type":"profile","op":"contains","sf":"email","v":"@"}]}', - upgrade_availability_item(0, 0, 0, 0, 1, array(), array($fieldrec))); - $fieldrec->operator = 'isnotempty'; - $fieldrec->userfield = null; - $fieldrec->shortname = 'frogtype'; - $this->assertEquals( - '{"op":"&","showc":[false],"c":[{"type":"profile","op":"isnotempty","cf":"frogtype"}]}', - upgrade_availability_item(0, 0, 0, 0, 0, array(), array($fieldrec))); - - // Everything at once. - $this->assertEquals('{"op":"&","showc":[false,true,false,true,true,true],' . - '"c":[{"type":"grouping","id":13},' . - '{"type":"date","d":">=","t":990},' . - '{"type":"date","d":"<","t":991},' . - '{"type":"grade","id":665,"min":70.00000},' . - '{"type":"completion","cm":42,"e":2},' . - '{"type":"profile","op":"isempty","sf":"email"}]}', - upgrade_availability_item(1, 13, 990, 991, 1, array( - (object)array('sourcecmid' => null, 'gradeitemid' => 665, 'grademin' => 70), - (object)array('sourcecmid' => 42, 'gradeitemid' => null, 'requiredcompletion' => 2) - ), array( - (object)array('userfield' => 'email', 'shortname' => null, 'operator' => 'isempty'), - ))); - } - /** * Test upgrade minmaxgrade step. */ @@ -488,6 +254,8 @@ public function test_upgrade_extra_credit_weightoverride() { $this->resetAfterTest(true); + require_once($CFG->libdir . '/db/upgradelib.php'); + $c = array(); $a = array(); $gi = array(); @@ -551,8 +319,11 @@ public function test_upgrade_extra_credit_weightoverride() { */ public function test_upgrade_calculated_grade_items_freeze() { global $DB, $CFG; + $this->resetAfterTest(); + require_once($CFG->libdir . '/db/upgradelib.php'); + // Create a user. $user = $this->getDataGenerator()->create_user(); @@ -679,8 +450,11 @@ public function test_upgrade_calculated_grade_items_freeze() { function test_upgrade_calculated_grade_items_regrade() { global $DB, $CFG; + $this->resetAfterTest(); + require_once($CFG->libdir . '/db/upgradelib.php'); + // Create a user. $user = $this->getDataGenerator()->create_user(); @@ -743,9 +517,12 @@ function test_upgrade_calculated_grade_items_regrade() { } public function test_upgrade_course_tags() { - global $DB; + global $DB, $CFG; + $this->resetAfterTest(); + require_once($CFG->libdir . '/db/upgradelib.php'); + // Running upgrade script when there are no tags. upgrade_course_tags(); $this->assertFalse($DB->record_exists('tag_instance', array())); diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 255b7647e4105..50cc8dadf4a59 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -3,6 +3,19 @@ information provided here is intended especially for developers. === 3.1 === +* The following functions, previously used (exclusively) by upgrade steps are not available + anymore because of the upgrade cleanup performed for this version. See MDL-51580 for more info: + - upgrade_mysql_fix_unsigned_and_lob_columns() + - upgrade_course_completion_remove_duplicates() + - upgrade_save_orphaned_questions() + - upgrade_rename_old_backup_files_using_shortname() + - upgrade_mssql_nvarcharmax() + - upgrade_mssql_varbinarymax() + - upgrade_fix_missing_root_folders() + - upgrade_course_modules_sequences() + - upgrade_grade_item_fix_sortorder() + - upgrade_availability_item() + * Plugins can extend the navigation for user by declaring the following callback: _extend_navigation_user(navigation_node $parentnode, stdClass $user, context_user $context, stdClass $course, diff --git a/lib/upgradelib.php b/lib/upgradelib.php index 1771153be9097..4f96d38b370f1 100644 --- a/lib/upgradelib.php +++ b/lib/upgradelib.php @@ -1915,300 +1915,6 @@ function admin_mnet_method_profile(Zend_Server_Reflection_Function_Abstract $fun return $profile; } - -/** - * This function finds duplicate records (based on combinations of fields that should be unique) - * and then progamatically generated a "most correct" version of the data, update and removing - * records as appropriate - * - * Thanks to Dan Marsden for help - * - * @param string $table Table name - * @param array $uniques Array of field names that should be unique - * @param array $fieldstocheck Array of fields to generate "correct" data from (optional) - * @return void - */ -function upgrade_course_completion_remove_duplicates($table, $uniques, $fieldstocheck = array()) { - global $DB; - - // Find duplicates - $sql_cols = implode(', ', $uniques); - - $sql = "SELECT {$sql_cols} FROM {{$table}} GROUP BY {$sql_cols} HAVING (count(id) > 1)"; - $duplicates = $DB->get_recordset_sql($sql, array()); - - // Loop through duplicates - foreach ($duplicates as $duplicate) { - $pointer = 0; - - // Generate SQL for finding records with these duplicate uniques - $sql_select = implode(' = ? AND ', $uniques).' = ?'; // builds "fieldname = ? AND fieldname = ?" - $uniq_values = array(); - foreach ($uniques as $u) { - $uniq_values[] = $duplicate->$u; - } - - $sql_order = implode(' DESC, ', $uniques).' DESC'; // builds "fieldname DESC, fieldname DESC" - - // Get records with these duplicate uniques - $records = $DB->get_records_select( - $table, - $sql_select, - $uniq_values, - $sql_order - ); - - // Loop through and build a "correct" record, deleting the others - $needsupdate = false; - $origrecord = null; - foreach ($records as $record) { - $pointer++; - if ($pointer === 1) { // keep 1st record but delete all others. - $origrecord = $record; - } else { - // If we have fields to check, update original record - if ($fieldstocheck) { - // we need to keep the "oldest" of all these fields as the valid completion record. - // but we want to ignore null values - foreach ($fieldstocheck as $f) { - if ($record->$f && (($origrecord->$f > $record->$f) || !$origrecord->$f)) { - $origrecord->$f = $record->$f; - $needsupdate = true; - } - } - } - $DB->delete_records($table, array('id' => $record->id)); - } - } - if ($needsupdate || isset($origrecord->reaggregate)) { - // If this table has a reaggregate field, update to force recheck on next cron run - if (isset($origrecord->reaggregate)) { - $origrecord->reaggregate = time(); - } - $DB->update_record($table, $origrecord); - } - } -} - -/** - * Find questions missing an existing category and associate them with - * a category which purpose is to gather them. - * - * @return void - */ -function upgrade_save_orphaned_questions() { - global $DB; - - // Looking for orphaned questions - $orphans = $DB->record_exists_select('question', - 'NOT EXISTS (SELECT 1 FROM {question_categories} WHERE {question_categories}.id = {question}.category)'); - if (!$orphans) { - return; - } - - // Generate a unique stamp for the orphaned questions category, easier to identify it later on - $uniquestamp = "unknownhost+120719170400+orphan"; - $systemcontext = context_system::instance(); - - // Create the orphaned category at system level - $cat = $DB->get_record('question_categories', array('stamp' => $uniquestamp, - 'contextid' => $systemcontext->id)); - if (!$cat) { - $cat = new stdClass(); - $cat->parent = 0; - $cat->contextid = $systemcontext->id; - $cat->name = get_string('orphanedquestionscategory', 'question'); - $cat->info = get_string('orphanedquestionscategoryinfo', 'question'); - $cat->sortorder = 999; - $cat->stamp = $uniquestamp; - $cat->id = $DB->insert_record("question_categories", $cat); - } - - // Set a category to those orphans - $params = array('catid' => $cat->id); - $DB->execute('UPDATE {question} SET category = :catid WHERE NOT EXISTS - (SELECT 1 FROM {question_categories} WHERE {question_categories}.id = {question}.category)', $params); -} - -/** - * Rename old backup files to current backup files. - * - * When added the setting 'backup_shortname' (MDL-28657) the backup file names did not contain the id of the course. - * Further we fixed that behaviour by forcing the id to be always present in the file name (MDL-33812). - * This function will explore the backup directory and attempt to rename the previously created files to include - * the id in the name. Doing this will put them back in the process of deleting the excess backups for each course. - * - * This function manually recreates the file name, instead of using - * {@link backup_plan_dbops::get_default_backup_filename()}, use it carefully if you're using it outside of the - * usual upgrade process. - * - * @see backup_cron_automated_helper::remove_excess_backups() - * @link http://tracker.moodle.org/browse/MDL-35116 - * @return void - * @since Moodle 2.4 - */ -function upgrade_rename_old_backup_files_using_shortname() { - global $CFG; - $dir = get_config('backup', 'backup_auto_destination'); - $useshortname = get_config('backup', 'backup_shortname'); - if (empty($dir) || !is_dir($dir) || !is_writable($dir)) { - return; - } - - require_once($CFG->dirroot.'/backup/util/includes/backup_includes.php'); - $backupword = str_replace(' ', '_', core_text::strtolower(get_string('backupfilename'))); - $backupword = trim(clean_filename($backupword), '_'); - $filename = $backupword . '-' . backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-'; - $regex = '#^'.preg_quote($filename, '#').'.*\.mbz$#'; - $thirtyapril = strtotime('30 April 2012 00:00'); - - // Reading the directory. - if (!$files = scandir($dir)) { - return; - } - foreach ($files as $file) { - // Skip directories and files which do not start with the common prefix. - // This avoids working on files which are not related to this issue. - if (!is_file($dir . '/' . $file) || !preg_match($regex, $file)) { - continue; - } - - // Extract the information from the XML file. - try { - $bcinfo = backup_general_helper::get_backup_information_from_mbz($dir . '/' . $file); - } catch (backup_helper_exception $e) { - // Some error while retrieving the backup informations, skipping... - continue; - } - - // Make sure this a course backup. - if ($bcinfo->format !== backup::FORMAT_MOODLE || $bcinfo->type !== backup::TYPE_1COURSE) { - continue; - } - - // Skip the backups created before the short name option was initially introduced (MDL-28657). - // This was integrated on the 2nd of May 2012. Let's play safe with timezone and use the 30th of April. - if ($bcinfo->backup_date < $thirtyapril) { - continue; - } - - // Let's check if the file name contains the ID where it is supposed to be, if it is the case then - // we will skip the file. Of course it could happen that the course ID is identical to the course short name - // even though really unlikely, but then renaming this file is not necessary. If the ID is not found in the - // file name then it was probably the short name which was used. - $idfilename = $filename . $bcinfo->original_course_id . '-'; - $idregex = '#^'.preg_quote($idfilename, '#').'.*\.mbz$#'; - if (preg_match($idregex, $file)) { - continue; - } - - // Generating the file name manually. We do not use backup_plan_dbops::get_default_backup_filename() because - // it will query the database to get some course information, and the course could not exist any more. - $newname = $filename . $bcinfo->original_course_id . '-'; - if ($useshortname) { - $shortname = str_replace(' ', '_', $bcinfo->original_course_shortname); - $shortname = core_text::strtolower(trim(clean_filename($shortname), '_')); - $newname .= $shortname . '-'; - } - - $backupdateformat = str_replace(' ', '_', get_string('backupnameformat', 'langconfig')); - $date = userdate($bcinfo->backup_date, $backupdateformat, 99, false); - $date = core_text::strtolower(trim(clean_filename($date), '_')); - $newname .= $date; - - if (isset($bcinfo->root_settings['users']) && !$bcinfo->root_settings['users']) { - $newname .= '-nu'; - } else if (isset($bcinfo->root_settings['anonymize']) && $bcinfo->root_settings['anonymize']) { - $newname .= '-an'; - } - $newname .= '.mbz'; - - // Final check before attempting the renaming. - if ($newname == $file || file_exists($dir . '/' . $newname)) { - continue; - } - @rename($dir . '/' . $file, $dir . '/' . $newname); - } -} - -/** - * Detect duplicate grade item sortorders and resort the - * items to remove them. - */ -function upgrade_grade_item_fix_sortorder() { - global $DB; - - // The simple way to fix these sortorder duplicates would be simply to resort each - // affected course. But in order to reduce the impact of this upgrade step we're trying - // to do it more efficiently by doing a series of update statements rather than updating - // every single grade item in affected courses. - - $sql = "SELECT DISTINCT g1.courseid - FROM {grade_items} g1 - JOIN {grade_items} g2 ON g1.courseid = g2.courseid - WHERE g1.sortorder = g2.sortorder AND g1.id != g2.id - ORDER BY g1.courseid ASC"; - foreach ($DB->get_fieldset_sql($sql) as $courseid) { - $transaction = $DB->start_delegated_transaction(); - $items = $DB->get_records('grade_items', array('courseid' => $courseid), '', 'id, sortorder, sortorder AS oldsort'); - - // Get all duplicates in course order, highest sort order, and higest id first so that we can make space at the - // bottom higher end of the sort orders and work down by id. - $sql = "SELECT DISTINCT g1.id, g1.sortorder - FROM {grade_items} g1 - JOIN {grade_items} g2 ON g1.courseid = g2.courseid - WHERE g1.sortorder = g2.sortorder AND g1.id != g2.id AND g1.courseid = :courseid - ORDER BY g1.sortorder DESC, g1.id DESC"; - - // This is the O(N*N) like the database version we're replacing, but at least the constants are a billion times smaller... - foreach ($DB->get_records_sql($sql, array('courseid' => $courseid)) as $duplicate) { - foreach ($items as $item) { - if ($item->sortorder > $duplicate->sortorder || ($item->sortorder == $duplicate->sortorder && $item->id > $duplicate->id)) { - $item->sortorder += 1; - } - } - } - foreach ($items as $item) { - if ($item->sortorder != $item->oldsort) { - $DB->update_record('grade_items', array('id' => $item->id, 'sortorder' => $item->sortorder)); - } - } - - $transaction->allow_commit(); - } -} - -/** - * Detect file areas with missing root directory records and add them. - */ -function upgrade_fix_missing_root_folders() { - global $DB, $USER; - - $transaction = $DB->start_delegated_transaction(); - - $sql = "SELECT contextid, component, filearea, itemid - FROM {files} - WHERE (component <> 'user' OR filearea <> 'draft') - GROUP BY contextid, component, filearea, itemid - HAVING MAX(CASE WHEN filename = '.' AND filepath = '/' THEN 1 ELSE 0 END) = 0"; - - $rs = $DB->get_recordset_sql($sql); - $defaults = array('filepath' => '/', - 'filename' => '.', - 'userid' => 0, // Don't rely on any particular user for these system records. - 'filesize' => 0, - 'timecreated' => time(), - 'timemodified' => time(), - 'contenthash' => sha1('')); - foreach ($rs as $r) { - $pathhash = sha1("/$r->contextid/$r->component/$r->filearea/$r->itemid/."); - $DB->insert_record('files', (array)$r + $defaults + - array('pathnamehash' => $pathhash)); - } - $rs->close(); - $transaction->allow_commit(); -} - /** * Detect draft file areas with missing root directory records and add them. */ diff --git a/mod/assignment/db/upgradelib.php b/mod/assignment/db/upgradelib.php deleted file mode 100644 index d245d359fc155..0000000000000 --- a/mod/assignment/db/upgradelib.php +++ /dev/null @@ -1,54 +0,0 @@ -. - -/** - * Assignment upgrade script. - * - * @package mod_assignment - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Inform admins about assignments that still need upgrading. - */ -function mod_assignment_pending_upgrades_notification($count) { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - - $a = new stdClass; - $a->count = $count; - $a->docsurl = get_docs_url('Assignment_upgrade_tool'); - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = \core_user::get_noreply_user(); - $message->userto = $admin; - $message->smallmessage = get_string('pendingupgrades_message_small', 'mod_assignment'); - $message->subject = get_string('pendingupgrades_message_subject', 'mod_assignment'); - $message->fullmessage = get_string('pendingupgrades_message_content', 'mod_assignment', $a); - $message->fullmessagehtml = get_string('pendingupgrades_message_content', 'mod_assignment', $a); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/mod/book/db/upgradelib.php b/mod/book/db/upgradelib.php deleted file mode 100644 index 73d0a0af59a1d..0000000000000 --- a/mod/book/db/upgradelib.php +++ /dev/null @@ -1,172 +0,0 @@ -. - -/** - * Book module upgrade related helper functions - * - * @package mod_book - * @copyright 2010 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die; - -/** - * Migrate book files stored in moddata folders. - * - * Please note it was a big mistake to store the files there in the first place! - * - * @param stdClass $book - * @param stdClass $context - * @param string $path - * @return void - */ -function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) { - global $OUTPUT, $CFG; - - $base = "$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id"; - $fulldir = $base.$path; - - if (!is_dir($fulldir)) { - // does not exist - return; - } - - $fs = get_file_storage(); - $items = new DirectoryIterator($fulldir); - - foreach ($items as $item) { - if ($item->isDot()) { - unset($item); // release file handle - continue; - } - - if ($item->isLink()) { - // do not follow symlinks - they were never supported in moddata, sorry - unset($item); // release file handle - continue; - } - - if ($item->isFile()) { - if (!$item->isReadable()) { - echo $OUTPUT->notification(" File not readable, skipping: ".$fulldir.$item->getFilename()); - unset($item); // release file handle - continue; - } - - $filepath = clean_param("/$CFG->moddata/book/$book->id".$path, PARAM_PATH); - $filename = clean_param($item->getFilename(), PARAM_FILE); - - if ($filename === '') { - // unsupported chars, sorry - unset($item); // release file handle - continue; - } - - if (core_text::strlen($filepath) > 255) { - echo $OUTPUT->notification(" File path longer than 255 chars, skipping: ".$fulldir.$item->getFilename()); - unset($item); // release file handle - continue; - } - - if (!$fs->file_exists($context->id, 'course', 'legacy', '0', $filepath, $filename)) { - $file_record = array('contextid'=>$context->id, 'component'=>'course', 'filearea'=>'legacy', 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename, - 'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime()); - $fs->create_file_from_pathname($file_record, $fulldir.$item->getFilename()); - } - $oldpathname = $fulldir.$item->getFilename(); - unset($item); // release file handle - @unlink($oldpathname); - - } else { - // migrate recursively all subdirectories - $oldpathname = $base.$item->getFilename().'/'; - $subpath = $path.$item->getFilename().'/'; - unset($item); // release file handle - mod_book_migrate_moddata_dir_to_legacy($book, $context, $subpath); - @rmdir($oldpathname); // deletes dir if empty - } - } - unset($items); // release file handles -} - -/** - * Migrate legacy files in intro and chapters - * @return void - */ -function mod_book_migrate_all_areas() { - global $DB, $OUTPUT; - - $rsbooks = $DB->get_recordset('book'); - foreach($rsbooks as $book) { - upgrade_set_timeout(360); // set up timeout, may also abort execution - $cm = get_coursemodule_from_instance('book', $book->id); - if (empty($cm) || empty($cm->id)) { - echo $OUTPUT->notification("Course module not found, skipping: {$book->name}"); - continue; - } - $context = context_module::instance($cm->id); - mod_book_migrate_area($book, 'intro', 'book', $book->course, $context, 'mod_book', 'intro', 0); - - $rschapters = $DB->get_recordset('book_chapters', array('bookid'=>$book->id)); - foreach ($rschapters as $chapter) { - mod_book_migrate_area($chapter, 'content', 'book_chapters', $book->course, $context, 'mod_book', 'chapter', $chapter->id); - } - $rschapters->close(); - } - $rsbooks->close(); -} - -/** - * Migrate one area, this should be probably part of moodle core... - * - * @param stdClass $record object to migrate files (book, chapter) - * @param string $field field in the record we are going to migrate - * @param string $table DB table containing the information to migrate - * @param int $courseid id of the course the book module belongs to - * @param context_module $context context of the book module - * @param string $component component to be used for the migrated files - * @param string $filearea filearea to be used for the migrated files - * @param int $itemid id to be used for the migrated files - * @return void - */ -function mod_book_migrate_area($record, $field, $table, $courseid, $context, $component, $filearea, $itemid) { - global $CFG, $DB; - - $fs = get_file_storage(); - - foreach(array(get_site()->id, $courseid) as $cid) { - $matches = null; - $ooldcontext = context_course::instance($cid); - if (preg_match_all("|$CFG->wwwroot/file.php(\?file=)?/$cid(/[^\s'\"&\?#]+)|", $record->$field, $matches)) { - $file_record = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid); - foreach ($matches[2] as $i=>$filepath) { - if (!$file = $fs->get_file_by_hash(sha1("/$ooldcontext->id/course/legacy/0".$filepath))) { - continue; - } - try { - if (!$newfile = $fs->get_file_by_hash(sha1("/$context->id/$component/$filearea/$itemid".$filepath))) { - $fs->create_file_from_storedfile($file_record, $file); - } - $record->$field = str_replace($matches[0][$i], '@@PLUGINFILE@@'.$filepath, $record->$field); - } catch (Exception $ex) { - // ignore problems - } - $DB->set_field($table, $field, $record->$field, array('id'=>$record->id)); - } - } - } -} \ No newline at end of file diff --git a/mod/book/upgrade.txt b/mod/book/upgrade.txt index 14dade6d51688..53f766d96d4c4 100644 --- a/mod/book/upgrade.txt +++ b/mod/book/upgrade.txt @@ -1,5 +1,13 @@ This files describes API changes in the book code. +=== 3.1 === + +* The following functions, previously used (exclusively) by upgrade steps are not available + anymore because of the upgrade cleanup performed for this version. See MDL-51580 for more info: + - mod_book_migrate_moddata_dir_to_legacy() + - mod_book_migrate_all_areas() + - mod_book_migrate_area() + === 3.0 === * External function mod_book_external::get_books_by_courses returned parameter "name" has been changed to PARAM_RAW, @@ -8,4 +16,4 @@ This files describes API changes in the book code. === 2.7 === * bogus legacy log calls were removed -* \mod_book\event\chapter_deleted::set_legacy_logdata() was removed \ No newline at end of file +* \mod_book\event\chapter_deleted::set_legacy_logdata() was removed diff --git a/portfolio/boxnet/db/upgradelib.php b/portfolio/boxnet/db/upgradelib.php deleted file mode 100644 index fe87bd6cbf744..0000000000000 --- a/portfolio/boxnet/db/upgradelib.php +++ /dev/null @@ -1,55 +0,0 @@ -. - -/** - * Locallib. - * - * @package portfolio_boxnet - * @copyright 2013 Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Send a message to the admin in regard with the APIv1 migration. - * - * @return void - */ -function portfolio_boxnet_admin_upgrade_notification() { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - $a = new stdClass(); - $a->docsurl = get_docs_url('Box.net_APIv1_migration'); - - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = get_admin(); - $message->userto = $admin; - $message->smallmessage = get_string('apiv1migration_message_small', 'portfolio_boxnet'); - $message->subject = get_string('apiv1migration_message_subject', 'portfolio_boxnet'); - $message->fullmessage = get_string('apiv1migration_message_content', 'portfolio_boxnet', $a); - $message->fullmessagehtml = get_string('apiv1migration_message_content', 'portfolio_boxnet', $a); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/portfolio/googledocs/db/upgradelib.php b/portfolio/googledocs/db/upgradelib.php deleted file mode 100644 index 4658ed8deb5ce..0000000000000 --- a/portfolio/googledocs/db/upgradelib.php +++ /dev/null @@ -1,53 +0,0 @@ -. - -/** - * Googledocs portfolio upgrade script. - * - * @package portfolio_googledocs - * @copyright 2013 Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Inform admins about setup required for googledocs change. - */ -function portfolio_googledocs_admin_upgrade_notification() { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - $a = new stdClass; - $a->docsurl = get_docs_url('Google_OAuth_2.0_setup'); - - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = get_admin(); - $message->userto = $admin; - $message->smallmessage = get_string('oauth2upgrade_message_small', 'portfolio_googledocs'); - $message->subject = get_string('oauth2upgrade_message_subject', 'portfolio_googledocs'); - $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_googledocs', $a); - $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_googledocs', $a); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/portfolio/picasa/db/upgradelib.php b/portfolio/picasa/db/upgradelib.php deleted file mode 100644 index a711cbfc46ff8..0000000000000 --- a/portfolio/picasa/db/upgradelib.php +++ /dev/null @@ -1,53 +0,0 @@ -. - -/** - * Picasa portfolio upgrade script. - * - * @package portfolio_picasa - * @copyright 2013 Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Inform admins about setup required for picasa change. - */ -function portfolio_picasa_admin_upgrade_notification() { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - $a = new stdClass; - $a->docsurl = get_docs_url('Google_OAuth_2.0_setup'); - - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = get_admin(); - $message->userto = $admin; - $message->smallmessage = get_string('oauth2upgrade_message_small', 'portfolio_picasa'); - $message->subject = get_string('oauth2upgrade_message_subject', 'portfolio_picasa'); - $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_picasa', $a); - $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_picasa', $a); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/portfolio/upgrade.txt b/portfolio/upgrade.txt index 557a33b34bc2a..49d49937e6c1a 100644 --- a/portfolio/upgrade.txt +++ b/portfolio/upgrade.txt @@ -1,6 +1,14 @@ This files describes API changes in /portfolio/ portfolio system, information provided here is intended especially for developers. +=== 3.1 === + +* The following functions, previously used (exclusively) by upgrade steps are not available + anymore because of the upgrade cleanup performed for this version. See MDL-51580 for more info: + - portfolio_picasa_admin_upgrade_notification() + - portfolio_googledocs_admin_upgrade_notification() + - portfolio_boxnet_admin_upgrade_notification() + === 2.4 === The set_callback_options function's third parameter has been changed from a file path diff --git a/question/type/upgrade.txt b/question/type/upgrade.txt index 2cd5513fcbb3f..470629c4b2618 100644 --- a/question/type/upgrade.txt +++ b/question/type/upgrade.txt @@ -1,5 +1,11 @@ This files describes API changes for question type plugins. +=== 3.1 === + +* The following functions, previously used (exclusively) by upgrade steps are not available + anymore because of the upgrade cleanup performed for this version. See MDL-51580 for more info: + - qtype_essay_convert_to_html() + === 2.7 === + We have added a new method to the question_type base class 'break_down_stats_and_response_analysis_by_variant'. By default it returns true. If your question type does not have variants of question instances then you can ignore this method as it only diff --git a/repository/alfresco/db/upgradelib.php b/repository/alfresco/db/upgradelib.php deleted file mode 100644 index 1a363e68542d4..0000000000000 --- a/repository/alfresco/db/upgradelib.php +++ /dev/null @@ -1,53 +0,0 @@ -. - -/** - * Locallib. - * - * @package repository_alfresco - * @copyright 2014 Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Send a message to the admin in regard with the APIv1 migration. - * - * @return void - */ -function repository_alfresco_admin_security_key_notice() { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = get_admin(); - $message->userto = $admin; - $message->smallmessage = get_string('security_key_notice_message_small', 'repository_alfresco'); - $message->subject = get_string('security_key_notice_message_subject', 'repository_alfresco'); - $message->fullmessage = get_string('security_key_notice_message_content', 'repository_alfresco'); - $message->fullmessagehtml = get_string('security_key_notice_message_content', 'repository_alfresco'); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/repository/boxnet/db/upgradelib.php b/repository/boxnet/db/upgradelib.php deleted file mode 100644 index c0cf9de80d635..0000000000000 --- a/repository/boxnet/db/upgradelib.php +++ /dev/null @@ -1,55 +0,0 @@ -. - -/** - * Locallib. - * - * @package repository_boxnet - * @copyright 2013 Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Send a message to the admin in regard with the APIv1 migration. - * - * @return void - */ -function repository_boxnet_admin_upgrade_notification() { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - $a = new stdClass(); - $a->docsurl = get_docs_url('Box.net_APIv1_migration'); - - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = get_admin(); - $message->userto = $admin; - $message->smallmessage = get_string('apiv1migration_message_small', 'repository_boxnet'); - $message->subject = get_string('apiv1migration_message_subject', 'repository_boxnet'); - $message->fullmessage = get_string('apiv1migration_message_content', 'repository_boxnet', $a); - $message->fullmessagehtml = get_string('apiv1migration_message_content', 'repository_boxnet', $a); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/repository/googledocs/db/upgradelib.php b/repository/googledocs/db/upgradelib.php deleted file mode 100644 index c065bd0a87e4f..0000000000000 --- a/repository/googledocs/db/upgradelib.php +++ /dev/null @@ -1,53 +0,0 @@ -. - -/** - * Googledocs repository upgrade script. - * - * @package repository_googledocs - * @copyright 2013 Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Inform admins about setup required for googledocs change. - */ -function repository_googledocs_admin_upgrade_notification() { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - - $a = new stdClass; - $a->docsurl = get_docs_url('Google_OAuth_2.0_setup'); - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = get_admin(); - $message->userto = $admin; - $message->smallmessage = get_string('oauth2upgrade_message_small', 'repository_googledocs'); - $message->subject = get_string('oauth2upgrade_message_subject', 'repository_googledocs'); - $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_googledocs', $a); - $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_googledocs', $a); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/repository/picasa/db/upgradelib.php b/repository/picasa/db/upgradelib.php deleted file mode 100644 index 4d76af52bef06..0000000000000 --- a/repository/picasa/db/upgradelib.php +++ /dev/null @@ -1,53 +0,0 @@ -. - -/** - * Picasa repository upgrade script. - * - * @package repository_picasa - * @copyright 2013 Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Inform admins about setup required for google picasa change. - */ -function repository_picasa_admin_upgrade_notification() { - $admins = get_admins(); - - if (empty($admins)) { - return; - } - $a = new stdClass; - $a->docsurl = get_docs_url('Google_OAuth_2.0_setup'); - - foreach ($admins as $admin) { - $message = new stdClass(); - $message->component = 'moodle'; - $message->name = 'notices'; - $message->userfrom = get_admin(); - $message->userto = $admin; - $message->smallmessage = get_string('oauth2upgrade_message_small', 'repository_picasa'); - $message->subject = get_string('oauth2upgrade_message_subject', 'repository_picasa'); - $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_picasa', $a); - $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_picasa', $a); - $message->fullmessageformat = FORMAT_PLAIN; - $message->notification = 1; - message_send($message); - } -} diff --git a/repository/upgrade.txt b/repository/upgrade.txt index e47ba3be344f4..e190f817c8b0f 100644 --- a/repository/upgrade.txt +++ b/repository/upgrade.txt @@ -3,6 +3,15 @@ information provided here is intended especially for developers. Full details of the repository API are available on Moodle docs: http://docs.moodle.org/dev/Repository_API +=== 3.1 === + +* The following functions, previously used (exclusively) by upgrade steps are not available + anymore because of the upgrade cleanup performed for this version. See MDL-51580 for more info: + - repository_picasa_admin_upgrade_notification() + - repository_googledocs_admin_upgrade_notification() + - repository_boxnet_admin_upgrade_notification() + - repository_alfresco_admin_security_key_notice() + === 2.8 === * Repositories working with Moodle files must replace serialize() with json_encode() in the