MDL-21432 - backup finished groupings restore + introduced role precheck/execution step
This commit is contained in:
@@ -40,6 +40,9 @@ class restore_root_task extends restore_task {
|
||||
// If we haven't preloaded information, load all the included inforef records to temp_ids table
|
||||
$this->add_step(new restore_load_included_inforef_records('load_inforef_records'));
|
||||
|
||||
// If we haven't preloaded information, load all the needed roles to temp_ids_table
|
||||
$this->add_step(new restore_load_and_map_roles('load_and_map_roles'));
|
||||
|
||||
// If we haven't preloaded information and are restoring user info, load all the needed users to temp_ids table
|
||||
$this->add_step(new restore_load_included_users('load_user_records'));
|
||||
|
||||
|
||||
@@ -108,15 +108,41 @@ class restore_load_included_files extends restore_structure_step {
|
||||
|
||||
// load it if needed:
|
||||
// - it it is one of the annotated inforef files (course/section/activity/block)
|
||||
// - it is one "user", "group" or "grade" component file
|
||||
// - it is one "user", "group", "grouping" or "grade" component file (that aren't sent to inforef ever)
|
||||
$isfileref = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'fileref', $data->id);
|
||||
$iscomponent = ($data->component == 'user' || $data->component == 'group' || $data->component == 'grade');
|
||||
$iscomponent = ($data->component == 'user' || $data->component == 'group' ||
|
||||
$data->component == 'grouping' || $data->component == 'grade');
|
||||
if ($isfileref || $iscomponent) {
|
||||
restore_dbops::set_backup_files_record($this->get_restoreid(), $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execution step that, *conditionally* (if there isn't preloaded information),
|
||||
* will load all the needed roles to backup_temp_ids. They will be stored with
|
||||
* "role" itemname. Also it will perform one automatic mapping to roles existing
|
||||
* in the target site, based in permissions of the user performing the restore,
|
||||
* archetypes and other bits. At the end, each original role will have its associated
|
||||
* target role or 0 if it's going to be skipped. Note we wrap everything over one
|
||||
* restore_dbops method, as far as the same stuff is going to be also executed
|
||||
* by restore prechecks
|
||||
*/
|
||||
class restore_load_and_map_roles extends restore_execution_step {
|
||||
|
||||
protected function define_execution() {
|
||||
if ($this->task->get_preloaded_information()) { // if info is already preloaded, nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
$file = $this->get_basepath() . '/roles.xml';
|
||||
// Load needed toles to temp_ids
|
||||
restore_dbops::load_roles_to_tempids($this->get_restoreid(), $file);
|
||||
// Process roles, mapping/skipping. Any error throws exception
|
||||
restore_dbops::process_included_roles($this->get_restoreid(), $this->task->get_courseid(), $this->task->get_userid(), $this->task->is_samesite());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execution step that, *conditionally* (if there isn't preloaded information
|
||||
* and users have been selected in settings, will load all the needed users
|
||||
@@ -243,17 +269,53 @@ class restore_groups_structure_step extends restore_structure_step {
|
||||
}
|
||||
|
||||
public function process_grouping($data) {
|
||||
debugging('TODO: Grouping restore not implemented. Detected grouping', DEBUG_DEVELOPER);
|
||||
global $DB;
|
||||
|
||||
$data = (object)$data; // handy
|
||||
$data->courseid = $this->get_courseid();
|
||||
|
||||
$oldid = $data->id; // need this saved for later
|
||||
$restorefiles = false; // Only if we end creating the grouping
|
||||
|
||||
// Search if the grouping already exists (by name & description) in the target course
|
||||
$description_clause = '';
|
||||
$params = array('courseid' => $this->get_courseid(), 'grname' => $data->name);
|
||||
if (!empty($data->description)) {
|
||||
$description_clause = ' AND ' .
|
||||
$DB->sql_compare_text('description') . ' = ' . $DB->sql_compare_text(':desc');
|
||||
$params['desc'] = $data->description;
|
||||
}
|
||||
if (!$groupingdb = $DB->get_record_sql("SELECT *
|
||||
FROM {groupings}
|
||||
WHERE courseid = :courseid
|
||||
AND name = :grname $description_clause", $params)) {
|
||||
// grouping doesn't exist, create
|
||||
$newitemid = $DB->insert_record('groupings', $data);
|
||||
$restorefiles = true; // We'll restore the files
|
||||
} else {
|
||||
// grouping exists, use it
|
||||
$newitemid = $groupingdb->id;
|
||||
}
|
||||
// Save the id mapping
|
||||
$this->set_mapping('grouping', $oldid, $newitemid, $restorefiles);
|
||||
}
|
||||
|
||||
public function process_grouping_group($data) {
|
||||
debugging('TODO: Grouping restore not implemented. Detected grouping group', DEBUG_DEVELOPER);
|
||||
global $DB;
|
||||
|
||||
$data = (object)$data;
|
||||
|
||||
$data->groupingid = $this->get_new_parentid('grouping'); // Use new parentid
|
||||
$data->groupid = $this->get_mappingid('group', $data->groupid); // Get from mappings
|
||||
$DB->insert_record('groupings_groups', $data); // No need to set this mapping (no child info nor files)
|
||||
}
|
||||
|
||||
protected function after_execute() {
|
||||
// Add group related files, matching with "group" mappings
|
||||
$this->add_related_files('group', 'icon', 'group');
|
||||
$this->add_related_files('group', 'description', 'group');
|
||||
// Add grouping related files, matching with "grouping" mappings
|
||||
$this->add_related_files('grouping', 'description', 'grouping');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -339,6 +401,7 @@ class restore_course_structure_step extends restore_structure_step {
|
||||
|
||||
// Processing functions go here
|
||||
public function process_course($data) {
|
||||
// TODO: don't forget to remap defaultgroupingid
|
||||
print_object('stopped before processing course. Continue here');
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,50 @@ abstract class restore_dbops {
|
||||
$xmlparser->process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the needed role.xml file to backup_ids table for future reference
|
||||
*/
|
||||
public static function load_roles_to_tempids($restoreid, $rolesfile) {
|
||||
|
||||
if (!file_exists($rolesfile)) { // Shouldn't happen ever, but...
|
||||
throw new backup_helper_exception('missing_roles_xml_file', $rolesfile);
|
||||
}
|
||||
// Let's parse, custom processor will do its work, sending info to DB
|
||||
$xmlparser = new progressive_parser();
|
||||
$xmlparser->set_file($rolesfile);
|
||||
$xmlprocessor = new restore_roles_parser_processor($restoreid);
|
||||
$xmlparser->set_processor($xmlprocessor);
|
||||
$xmlparser->process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Precheck the loaded roles, return empty array if everything is ok, and
|
||||
* array with 'errors', 'warnings' elements (suitable to be used by restore_prechecks)
|
||||
* with any problem found
|
||||
*/
|
||||
public static function precheck_included_roles($restoreid, $courseid, $userid, $samesite) {
|
||||
debugging('implement the roles mapping/skip here. returns errors/warnings array', DEBUG_DEVELOPER);
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the loaded roles, looking for their best mapping or skipping
|
||||
* Any error will cause exception. Note this is one wrapper over
|
||||
* precheck_included_roles, that contains all the logic, but returns
|
||||
* errors/warnings instead and is executed as part of the restore prechecks
|
||||
*/
|
||||
public static function process_included_roles($restoreid, $courseid, $userid, $samesite) {
|
||||
global $DB;
|
||||
|
||||
// Just let precheck_included_roles() to do all the hard work
|
||||
$problems = self::precheck_included_roles($restoreid, $courseid, $userid, $samesite);
|
||||
|
||||
// With problems of type error, throw exception, shouldn't happen if prechecks executed
|
||||
if (array_key_exists('errors', $problems)) {
|
||||
throw new restore_dbops_exception('restore_problems_processing_roles', null, implode(', ', $problems['errors']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the needed users.xml file to backup_ids table for future reference
|
||||
*/
|
||||
@@ -152,9 +196,9 @@ abstract class restore_dbops {
|
||||
$params = array($restoreid, $oldcontextid, $component, $filearea, $itemname);
|
||||
}
|
||||
|
||||
$rs = $DB->get_recordset_sql($sql, $params);
|
||||
$fs = get_file_storage(); // Get moodle file storage
|
||||
$basepath = $basepath . '/files/';// Get backup file pool base
|
||||
$rs = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($rs as $rec) {
|
||||
$file = (object)unserialize(base64_decode($rec->info));
|
||||
// ignore root dirs (they are created automatically)
|
||||
|
||||
@@ -49,6 +49,15 @@ abstract class restore_prechecks_helper {
|
||||
$errors = array();
|
||||
$warnings = array();
|
||||
|
||||
// Some handy vars to be used along the prechecks
|
||||
$samesite = $controller->is_samesite();
|
||||
$restoreusers = $controller->get_plan()->get_setting('users')->get_value();
|
||||
$hasmnetusers = (int)$controller->get_info()->mnet_remoteusers;
|
||||
$restoreid = $controller->get_restoreid();
|
||||
$courseid = $controller->get_courseid();
|
||||
$userid = $controller->get_userid();
|
||||
$inforeffiles = restore_dbops::get_needed_inforef_files($restoreid); // Get all inforef files
|
||||
|
||||
// Create temp tables
|
||||
restore_controller_dbops::create_restore_temp_tables($controller->get_restoreid());
|
||||
|
||||
@@ -78,9 +87,6 @@ abstract class restore_prechecks_helper {
|
||||
}
|
||||
|
||||
// If restoring to different site and restoring users and backup has mnet users warn/error
|
||||
$samesite = $controller->is_samesite();
|
||||
$restoreusers = $controller->get_plan()->get_setting('users')->get_value();
|
||||
$hasmnetusers = (int)$controller->get_info()->mnet_remoteusers;
|
||||
if (!$samesite && $restoreusers && $hasmnetusers) {
|
||||
// User is admin (can create users at sysctx), warn
|
||||
if (has_capability('moodle/user:create', get_context_instance(CONTEXT_SYSTEM), $controller->get_userid())) {
|
||||
@@ -91,16 +97,14 @@ abstract class restore_prechecks_helper {
|
||||
}
|
||||
}
|
||||
|
||||
// Load all the inforef files, we are going to need them
|
||||
foreach ($inforeffiles as $inforeffile) {
|
||||
restore_dbops::load_inforef_to_tempids($restoreid, $inforeffile); // Load each inforef file to temp_ids
|
||||
}
|
||||
|
||||
// If restoring users, check we are able to create all them
|
||||
if ($restoreusers) {
|
||||
$file = $controller->get_plan()->get_basepath() . '/users.xml';
|
||||
$restoreid = $controller->get_restoreid();
|
||||
$courseid = $controller->get_courseid();
|
||||
$userid = $controller->get_userid();
|
||||
$inforeffiles = restore_dbops::get_needed_inforef_files($restoreid); // Get all inforef files
|
||||
foreach ($inforeffiles as $inforeffile) {
|
||||
restore_dbops::load_inforef_to_tempids($restoreid, $inforeffile); // Load each inforef file to temp_ids
|
||||
}
|
||||
restore_dbops::load_users_to_tempids($restoreid, $file); // Load needed users to temp_ids
|
||||
if ($problems = restore_dbops::precheck_included_users($restoreid, $courseid, $userid, $samesite)) {
|
||||
$errors = array_merge($errors, $problems);
|
||||
@@ -108,7 +112,13 @@ abstract class restore_prechecks_helper {
|
||||
}
|
||||
|
||||
// TODO: Perform role_mappings, warning about non-mappable ones being ignored (see 1.9)
|
||||
// (restore won't create roles in any case)
|
||||
// Note: restore won't create roles at all. Only mapping/skip!
|
||||
$file = $controller->get_plan()->get_basepath() . '/roles.xml';
|
||||
restore_dbops::load_roles_to_tempids($restoreid, $file); // Load needed users to temp_ids
|
||||
if ($problems = restore_dbops::precheck_included_roles($restoreid, $courseid, $userid, $samesite)) {
|
||||
$errors = array_key_exists('errors', $problems) ? array_merge($errors, $problems['errors']) : $errors;
|
||||
$warnings = array_key_exists('warnings', $problems) ? array_merge($warnings, $problems['warnings']) : $warnings;
|
||||
}
|
||||
|
||||
// Prepare results and return
|
||||
$results = array();
|
||||
|
||||
@@ -38,6 +38,7 @@ require_once($CFG->dirroot . '/backup/util/helper/restore_prechecks_helper.class
|
||||
require_once($CFG->dirroot . '/backup/util/helper/restore_moodlexml_parser_processor.class.php');
|
||||
require_once($CFG->dirroot . '/backup/util/helper/restore_inforef_parser_processor.class.php');
|
||||
require_once($CFG->dirroot . '/backup/util/helper/restore_users_parser_processor.class.php');
|
||||
require_once($CFG->dirroot . '/backup/util/helper/restore_roles_parser_processor.class.php');
|
||||
require_once($CFG->dirroot . '/backup/util/helper/restore_structure_parser_processor.class.php');
|
||||
require_once($CFG->dirroot . '/backup/util/xml/parser/progressive_parser.class.php');
|
||||
require_once($CFG->dirroot . '/backup/util/output/output_controller.class.php');
|
||||
|
||||
Reference in New Issue
Block a user