Last active
March 29, 2021 19:20
-
-
Save ericmerrill/e5f9ad3578cd40a980021d2be882a851 to your computer and use it in GitHub Desktop.
A file to backup calendar data out of a old Moodle copy and into a new one to fix issues raised in MDL-71156
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| // This file is part of Moodle - http://moodle.org/ | |
| // | |
| // Moodle is free software: you can redistribute it and/or modify | |
| // it under the terms of the GNU General Public License as published by | |
| // the Free Software Foundation, either version 3 of the License, or | |
| // (at your option) any later version. | |
| // | |
| // Moodle is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // | |
| // You should have received a copy of the GNU General Public License | |
| // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
| /** | |
| * Backup and restore calendar IDs to fix dataloss reported in MDL-71156. | |
| * | |
| * USE AT YOUR OWN RISK! | |
| * | |
| * Expects to be in admin/cli, although just modify the require line for | |
| * config.php if you want to change that. | |
| * | |
| * @copyright 2021 Eric Merrill <[email protected]> | |
| * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
| */ | |
| define('CLI_SCRIPT', true); | |
| require(__DIR__.'/../../config.php'); | |
| require_once("$CFG->libdir/clilib.php"); | |
| $longparams = [ | |
| 'backup' => null, | |
| 'help' => false, | |
| 'restorefile' => false, | |
| 'modulename' => false | |
| ]; | |
| $shortmappings = [ | |
| 'b' => 'backup', | |
| 'h' => 'help', | |
| 'f' => 'restorefile' | |
| ]; | |
| // Get CLI params. | |
| list($options, $unrecognized) = cli_get_params($longparams, $shortmappings); | |
| if ($unrecognized) { | |
| $unrecognized = implode("\n ", $unrecognized); | |
| cli_error(get_string('cliunknowoption', 'admin', $unrecognized)); | |
| } | |
| if (empty($options['help']) && empty($options['backup']) && empty($options['restorefile'])) { | |
| mtrace("--backup or --restorefile flag must be set"); | |
| $options['help'] = true; | |
| } | |
| if ($options['help']) { | |
| echo "THIS IS NOT AN OFFICIAL MOODLE FILE. USE AT YOUR OWN RISK! | |
| This file has two parts, used to fixup records from the issue reported in MDL-71156, if you have a | |
| live backup of the system. | |
| When used on a backup before the 3.10.2/3.9.5 update with the -b option, it will output rows of data | |
| (rowid, userid). Save that to a file on your post update system. | |
| If you do not have the backup on a live Moodle system that can run PHP code, you need to output from | |
| your backup database a file that has records from mdl_events that match the query: | |
| SELECT id, modulename, userid FROM mdl_event | |
| WHERE (eventtype <> 'user' OR priority <> 0) | |
| AND courseid = 0 | |
| AND groupid = 0 | |
| AND categoryid = 0 | |
| One per line, in the format of: | |
| id,modulename,userid | |
| id,modulename,userid | |
| id,modulename,userid | |
| On the post-update system (with broken records), you will use -f=/path/to/file/above.txt, and it | |
| will read the file, and correct the broken DB records to the best of its ability. | |
| Options: | |
| -b, --backup Output data to be used later by this script on another system | |
| -f, --restorefile=FILEPATH Takes a filepath and reads the contents. Uses the IDs to attempt to correct | |
| calendar records. Works on backup or restore step. | |
| --modulename=MODNAME Limit to the specified modulename | |
| -h, --help Print out this help | |
| Example: | |
| \$ sudo -u www-data /usr/bin/php admin/cli/cal_id_backup_restore.php.php -b > /home/u/user/backupfile.txt | |
| \$ sudo -u www-data /usr/bin/php admin/cli/cal_id_backup_restore.php.php -f=/home/u/user/backupfile.txt | |
| "; | |
| die; | |
| } | |
| $modfilter = false; | |
| if ($options['modulename']) { | |
| $modfilter = $options['modulename']; | |
| } | |
| if ($options['backup']) { | |
| $sql = "SELECT id, modulename, userid FROM {event} | |
| WHERE (eventtype <> 'user' OR priority <> 0) | |
| AND courseid = 0 | |
| AND groupid = 0 | |
| AND categoryid = 0"; | |
| $params = []; | |
| if ($modfilter) { | |
| $sql .= ' AND modulename = ?'; | |
| $params = [$modfilter]; | |
| } | |
| $records = $DB->get_recordset_sql($sql, $params); | |
| foreach ($records as $record) { | |
| mtrace($record->id . ',' . $record->modulename . ',' . $record->userid); | |
| } | |
| $records->close(); | |
| } else if ($options['restorefile']) { | |
| $filepath = $options['restorefile']; | |
| if (!is_string($filepath) || !is_readable($filepath)) { | |
| cli_error('Input file cannot be found or is not readable'); | |
| } | |
| $fh = fopen($filepath, "r"); | |
| if (empty($fh)) { | |
| cli_error('Input file cannot be read'); | |
| } | |
| while ($line = fgets($fh)) { | |
| $line = trim($line); | |
| $parts = explode(',', $line); | |
| if (count($parts) != 3) { | |
| mtrace('ERROR: Incorrect number of items in line: ' . $line); | |
| continue; | |
| } | |
| $rowid = trim($parts[0]); | |
| $module = trim(trim($parts[1]), "'\""); // Trim quotes in case they we added on accident. | |
| $userid = trim($parts[2]); | |
| if (!is_numeric($rowid) || !is_numeric($userid) || empty($module)) { | |
| mtrace('ERROR: Incorrectly formatted data in line: ' . $line); | |
| continue; | |
| } | |
| if ($modfilter && $module != $modfilter) { | |
| mtrace("INFO: Skipping line because line doesn't match modulename flag: " . $line); | |
| continue; | |
| } | |
| $row = $DB->get_record('event', ['id' => $rowid]); | |
| if (empty($row)) { | |
| mtrace('INFO: Could not get row for line: ' . $line); | |
| continue; | |
| } | |
| if ($row->userid !== '0') { | |
| if ($row->userid == $userid) { | |
| mtrace('INFO: Row already has expected userid: ' . $line); | |
| continue; | |
| } | |
| mtrace('ERROR: Database row already has a userid and cannot be updated: ' . $line); | |
| continue; | |
| } | |
| if ($row->modulename !== $module) { | |
| mtrace('ERROR: Row\'s modulename doesn\'t match input line: ' . $line); | |
| continue; | |
| } | |
| if ($row->courseid !== '0' || $row->groupid !== '0' || $row->categoryid !== '0') { | |
| mtrace('ERROR: Retrieved record does not have an empty course, group, and/or category: ' . $line); | |
| continue; | |
| } | |
| $DB->set_field('event', 'userid', $userid, ['id' => $row->id]); | |
| mtrace('INFO: Updated userid for row: ' . $line); | |
| } | |
| fclose($fh); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanx a lot fot this script!
It helps us to fix our broken records on a quite large install which, unfortunately, has been upgraded last saturday to 3.10.2... so again: thank you very much