backup MDL-22254 Added backup and restore of course completion information

This commit is contained in:
Sam Hemelryk 2010-09-17 03:04:55 +00:00
parent f64e29e133
commit bd39b6f226
7 changed files with 346 additions and 1 deletions

View File

@ -173,7 +173,7 @@ abstract class backup_activity_task extends backup_task {
// Find activity_included_setting
if (!$this->get_setting_value('included')) {
$this->log('activity skipped by _included setting', backup::LOG_DEBUG, $this->name);
$this->plan->set_excluding_activities();
} else { // Setting tells us it's ok to execute
parent::execute();
}

View File

@ -73,6 +73,9 @@ class backup_final_task extends backup_task {
// execute_condition() so only will be excuted if ALL module grade_items in course have been exported
$this->add_step(new backup_gradebook_structure_step('course_gradebook','gradebook.xml'));
// Generate the course completion
$this->add_step(new backup_course_completion_structure_step('course_completion', 'completion.xml'));
// Generate the scales file with all the (final) annotated scales
$this->add_step(new backup_final_scales_structure_step('scaleslist', 'scales.xml'));

View File

@ -1544,3 +1544,82 @@ class backup_activity_grades_structure_step extends backup_structure_step {
return $book;
}
}
/**
* Backups up the course completion information for the course.
*/
class backup_course_completion_structure_step extends backup_structure_step {
protected function execute_condition() {
// Check that all activities have been included
if ($this->task->is_excluding_activities()) {
return false;
}
return true;
}
/**
* The structure of the course completion backup
*
* @return backup_nested_element
*/
protected function define_structure() {
// To know if we are including user completion info
$userinfo = $this->get_setting_value('userscompletion');
$cc = new backup_nested_element('course_completion');
$criteria = new backup_nested_element('course_completion_criteria', array('id'), array(
'course','criteriatype', 'module', 'moduleinstance', 'courseinstanceshortname', 'enrolperiod', 'timeend', 'gradepass', 'role'
));
$criteriacompletions = new backup_nested_element('course_completion_crit_completions');
$criteriacomplete = new backup_nested_element('course_completion_crit_compl', array('id'), array(
'criteriaid', 'userid','gradefinal','unenrolled','deleted','timecompleted'
));
$coursecompletions = new backup_nested_element('course_completions', array('id'), array(
'userid', 'course', 'deleted', 'timenotified', 'timeenrolled','timestarted','timecompleted','reaggregate'
));
$notify = new backup_nested_element('course_completion_notify', array('id'), array(
'course','role','message','timesent'
));
$aggregatemethod = new backup_nested_element('course_completion_aggr_methd', array('id'), array(
'course','criteriatype','method','value'
));
$cc->add_child($criteria);
$criteria->add_child($criteriacompletions);
$criteriacompletions->add_child($criteriacomplete);
$cc->add_child($coursecompletions);
$cc->add_child($notify);
$cc->add_child($aggregatemethod);
// We need to get the courseinstances shortname rather than an ID for restore
$criteria->set_source_sql("SELECT ccc.*, c.shortname courseinstanceshortname
FROM {course_completion_criteria} ccc
LEFT JOIN {course} c ON c.id = ccc.courseinstance
WHERE ccc.course = ?", array(backup::VAR_COURSEID));
$notify->set_source_table('course_completion_notify', array('course' => backup::VAR_COURSEID));
$aggregatemethod->set_source_table('course_completion_aggr_methd', array('course' => backup::VAR_COURSEID));
if ($userinfo) {
$criteriacomplete->set_source_table('course_completion_crit_compl', array('criteriaid' => backup::VAR_PARENTID));
$coursecompletions->set_source_table('course_completions', array('course' => backup::VAR_COURSEID));
}
$criteria->annotate_ids('role', 'role');
$criteriacomplete->annotate_ids('user', 'userid');
$coursecompletions->annotate_ids('user', 'userid');
$notify->annotate_ids('role', 'role');
return $cc;
}
}

View File

@ -47,6 +47,9 @@ class restore_final_task extends restore_task {
$this->add_step(new restore_gradebook_structure_step('gradebook_step','gradebook.xml'));
}
// Course completion
$this->add_step(new restore_course_completion_structure_step('course_completion', 'completion.xml'));
// Review all the module_availability records in backup_ids in order
// to match them with existing modules / grade items.
$this->add_step(new restore_process_course_modules_availability('process_modules_availability'));

View File

@ -1226,6 +1226,253 @@ class restore_comments_structure_step extends restore_structure_step {
}
}
class restore_course_completion_structure_step extends restore_structure_step {
/**
* Conditionally decide if this step should be executed.
*
* This function checks parameters that are not immediate settings to ensure
* that the enviroment is suitable for the restore of course completion info.
*
* This function checks the following four parameters:
*
* 1. Course completion is enabled on the site
* 2. The backup includes course completion information
* 3. All modules are restorable
* 4. All modules are marked for restore.
*
* @return bool True is safe to execute, false otherwise
*/
protected function execute_condition() {
global $CFG;
// First check course completion is enabled on this site
if (empty($CFG->enablecompletion)) {
// Disabled, don't restore course completion
return false;
}
// Check it is included in the backup
$fullpath = $this->task->get_taskbasepath();
$fullpath = rtrim($fullpath, '/') . '/' . $this->filename;
if (!file_exists($fullpath)) {
// Not found, can't restore course completion
return false;
}
// Check we are able to restore all backed up modules
if ($this->task->is_missing_modules()) {
return false;
}
// Finally check all modules within the backup are being restored.
if ($this->task->is_excluding_activities()) {
return false;
}
return true;
}
/**
* Define the course completion structure
*
* @return array Array of restore_path_element
*/
protected function define_structure() {
// To know if we are including user completion info
$userinfo = $this->get_setting_value('userscompletion');
$paths = array();
$paths[] = new restore_path_element('course_completion_criteria', '/course_completion/course_completion_criteria');
$paths[] = new restore_path_element('course_completion_notify', '/course_completion/course_completion_notify');
$paths[] = new restore_path_element('course_completion_aggr_methd', '/course_completion/course_completion_aggr_methd');
if ($userinfo) {
$paths[] = new restore_path_element('course_completion_crit_compl', '/course_completion/course_completion_criteria/course_completion_crit_completions/course_completion_crit_compl');
$paths[] = new restore_path_element('course_completions', '/course_completion/course_completions');
}
return $paths;
}
/**
* Process course completion criteria
*
* @global moodle_database $DB
* @param stdClass $data
*/
public function process_course_completion_criteria($data) {
global $DB;
$data = (object)$data;
$data->course = $this->get_courseid();
// Apply the date offset to the time end field
$data->timeend = $this->apply_date_offset($data->timeend);
// Map the role from the criteria
if (!empty($data->role)) {
$data->role = $this->get_mappingid('role', $data->role);
}
// If the completion criteria is for a module we need to map the module instance
// to the new module id.
if (!empty($data->moduleinstance) && !empty($data->module)) {
$data->moduleinstance = $this->get_mappingid('course_module', $data->moduleinstance);
} else {
$data->module = null;
$data->moduleinstance = null;
}
// We backup the course shortname rather than the ID so that we can match back to the course
$skipcriteria = false;
if (!empty($data->courseinstanceshortname)) {
$courseinstanceid = $DB->get_field('course', 'id', array('shortname'=>$data->courseinstanceshortname));
if (!$courseinstanceid) {
$skipcriteria = true;
}
} else {
$courseinstanceid = null;
}
$data->courseinstance = $courseinstanceid;
if (!$skipcriteria) {
$params = array(
'course' => $data->course,
'criteriatype' => $data->criteriatype,
'enrolperiod' => $data->enrolperiod,
'courseinstance' => $data->courseinstance,
'module' => $data->module,
'moduleinstance' => $data->moduleinstance,
'timeend' => $data->timeend,
'gradepass' => $data->gradepass,
'role' => $data->role
);
$newid = $DB->insert_record('course_completion_criteria', $params);
$this->set_mapping('course_completion_criteria', $data->id, $newid);
}
}
/**
* Processes course compltion criteria complete records
*
* @global moodle_database $DB
* @param stdClass $data
*/
public function process_course_completion_crit_compl($data) {
global $DB;
$data = (object)$data;
// This may be empty if criteria could not be restored
$data->criteriaid = $this->get_mappingid('course_completion_criteria', $data->criteriaid);
$data->course = $this->get_courseid();
$data->userid = $this->get_mappingid('user', $data->userid);
if (!empty($data->criteriaid) && !empty($data->userid)) {
$params = array(
'userid' => $data->userid,
'course' => $data->course,
'criteriaid' => $data->criteriaid,
'timecompleted' => $this->apply_date_offset($data->timecompleted)
);
if (isset($data->gradefinal)) {
$params['gradefinal'] = $data->gradefinal;
}
if (isset($data->unenroled)) {
$params['unenroled'] = $data->unenroled;
}
if (isset($data->deleted)) {
$params['deleted'] = $data->deleted;
}
$DB->insert_record('course_completion_crit_compl', $params);
}
}
/**
* Process course completions
*
* @global moodle_database $DB
* @param stdClass $data
*/
public function process_course_completions($data) {
global $DB;
$data = (object)$data;
$data->course = $this->get_courseid();
$data->userid = $this->get_mappingid('user', $data->userid);
if (!empty($data->userid)) {
$params = array(
'userid' => $data->userid,
'course' => $data->course,
'deleted' => $data->deleted,
'timenotified' => $this->apply_date_offset($data->timenotified),
'timeenrolled' => $this->apply_date_offset($data->timeenrolled),
'timestarted' => $this->apply_date_offset($data->timestarted),
'timecompleted' => $this->apply_date_offset($data->timecompleted),
'reaggregate' => $data->reaggregate
);
$DB->insert_record('course_completions', $params);
}
}
/**
* Process course completion notification records.
*
* Note: As of Moodle 2.0 this table is not being used however it has been
* left in in the hopes that one day the functionality there will be completed
*
* @global moodle_database $DB
* @param stdClass $data
*/
public function process_course_completion_notify($data) {
global $DB;
$data = (object)$data;
$data->course = $this->get_courseid();
if (!empty($data->role)) {
$data->role = $this->get_mappingid('role', $data->role);
}
$params = array(
'course' => $data->course,
'role' => $data->role,
'message' => $data->message,
'timesent' => $this->apply_date_offset($data->timesent),
);
$DB->insert_record('course_completion_notify', $params);
}
/**
* Process course completion aggregate methods
*
* @global moodle_database $DB
* @param stdClass $data
*/
public function process_course_completion_aggr_methd($data) {
global $DB;
$data = (object)$data;
$data->course = $this->get_courseid();
$params = array(
'course' => $data->course,
'criteriatype' => $data->criteriatype,
'method' => $data->method,
'value' => $data->value,
);
$DB->insert_record('course_completion_aggr_methd', $params);
}
}
/**
* This structure step restores the grade items associated with one activity
* All the grade items are made child of the "course" grade item but the original

View File

@ -31,6 +31,7 @@ class backup_plan extends base_plan implements loggable {
protected $controller; // The backup controller building/executing this plan
protected $basepath; // Fullpath to dir where backup is created
protected $excludingdactivities;
/**
* Constructor - instantiates one object of this class
@ -67,6 +68,14 @@ class backup_plan extends base_plan implements loggable {
return $this->controller->get_logger();
}
public function is_excluding_activities() {
return $this->excludingdactivities;
}
public function set_excluding_activities() {
$this->excludingdactivities = true;
}
public function log($message, $level, $a = null, $depth = null, $display = false) {
backup_helper::log($message, $level, $a, $depth, $display, $this->get_logger());
}

View File

@ -42,6 +42,10 @@ abstract class backup_task extends base_task {
public function get_backupid() {
return $this->plan->get_backupid();
}
public function is_excluding_activities() {
return $this->plan->is_excluding_activities();
}
}
/*