MDL-39558 badges: Add backup/restore to course badges
authorYuliya Bozhko <yuliya.bozhko@totaralms.com>
Fri, 14 Jun 2013 04:35:34 +0000 (16:35 +1200)
committerDamyon Wiese <damyon@moodle.com>
Wed, 3 Jul 2013 01:35:06 +0000 (09:35 +0800)
12 files changed:
admin/settings/courses.php
backup/moodle2/backup_final_task.class.php
backup/moodle2/backup_root_task.class.php
backup/moodle2/backup_settingslib.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_final_task.class.php
backup/moodle2/restore_root_task.class.php
backup/moodle2/restore_settingslib.php
backup/moodle2/restore_stepslib.php
backup/util/dbops/backup_controller_dbops.class.php
backup/util/helper/backup_cron_helper.class.php
lang/en/backup.php

index e751525..377034b 100644 (file)
@@ -158,6 +158,7 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_blocks', new lang_string('generalblocks','backup'), new lang_string('configgeneralblocks','backup'), array('value'=>1, 'locked'=>0)));
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_filters', new lang_string('generalfilters','backup'), new lang_string('configgeneralfilters','backup'), array('value'=>1, 'locked'=>0)));
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_comments', new lang_string('generalcomments','backup'), new lang_string('configgeneralcomments','backup'), array('value'=>1, 'locked'=>0)));
+    $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_badges', new lang_string('generalbadges','backup'), new lang_string('configgeneralbadges','backup'), array('value'=>1,'locked'=>0)));
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_userscompletion', new lang_string('generaluserscompletion','backup'), new lang_string('configgeneraluserscompletion','backup'), array('value'=>1, 'locked'=>0)));
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_logs', new lang_string('generallogs','backup'), new lang_string('configgenerallogs','backup'), array('value'=>0, 'locked'=>0)));
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_histories', new lang_string('generalhistories','backup'), new lang_string('configgeneralhistories','backup'), array('value'=>0, 'locked'=>0)));
@@ -231,6 +232,7 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_blocks', new lang_string('generalblocks','backup'), new lang_string('configgeneralblocks','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_filters', new lang_string('generalfilters','backup'), new lang_string('configgeneralfilters','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_comments', new lang_string('generalcomments','backup'), new lang_string('configgeneralcomments','backup'), 1));
+    $temp->add(new admin_setting_configcheckbox('backup/backup_auto_badges', new lang_string('generalbadges','backup'), new lang_string('configgeneralbadges','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_userscompletion', new lang_string('generaluserscompletion','backup'), new lang_string('configgeneraluserscompletion','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_logs', new lang_string('generallogs', 'backup'), new lang_string('configgenerallogs', 'backup'), 0));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_histories', new lang_string('generalhistories','backup'), new lang_string('configgeneralhistories','backup'), 0));
index 38bccb6..ad5ac4a 100644 (file)
@@ -92,6 +92,11 @@ class backup_final_task extends backup_task {
         // Generate the course completion
         $this->add_step(new backup_course_completion_structure_step('course_completion', 'completion.xml'));
 
+        // Conditionally generate the badges file.
+        if ($this->get_setting_value('badges')) {
+            $this->add_step(new backup_badges_structure_step('course_badges', 'badges.xml'));
+        }
+
         // Generate the scales file with all the (final) annotated scales
         $this->add_step(new backup_final_scales_structure_step('scaleslist', 'scales.xml'));
 
index cf25616..73daf10 100644 (file)
@@ -122,6 +122,12 @@ class backup_root_task extends backup_task {
         $this->add_setting($comments);
         $users->add_dependency($comments);
 
+        // Define badges (dependent of activities).
+        $badges = new backup_badges_setting('badges', base_setting::IS_BOOLEAN, true);
+        $badges->set_ui(new backup_setting_ui_checkbox($badges, get_string('rootsettingbadges', 'backup')));
+        $this->add_setting($badges);
+        $activities->add_dependency($badges);
+
         // Define calendar events (dependent of users)
         $events = new backup_calendarevents_setting('calendarevents', base_setting::IS_BOOLEAN, true);
         $events->set_ui(new backup_setting_ui_checkbox($events, get_string('rootsettingcalendarevents', 'backup')));
index ddd6aa2..b3704ab 100644 (file)
@@ -101,6 +101,12 @@ class backup_logs_setting extends backup_anonymize_setting {}
  */
 class backup_comments_setting extends backup_anonymize_setting {}
 
+/**
+ * root setting to control if backup will include badges or not,
+ * depends on @backup_activities_setting
+ */
+class backup_badges_setting extends backup_generic_setting {}
+
 /**
  * root setting to control if backup will include
  * calender events or no (any level), depends of @backup_users_setting
index d49bfa4..abf333a 100644 (file)
@@ -812,6 +812,71 @@ class backup_comments_structure_step extends backup_structure_step {
     }
 }
 
+/**
+ * structure step in charge of constructing the badges.xml file for all the badges found
+ * in a given context
+ */
+class backup_badges_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;
+    }
+
+    protected function define_structure() {
+
+        // Define each element separated.
+
+        $badges = new backup_nested_element('badges');
+        $badge = new backup_nested_element('badge', array('id'), array('name', 'description',
+                'timecreated', 'timemodified', 'usercreated', 'usermodified', 'issuername',
+                'issuerurl', 'issuercontact', 'expiredate', 'expireperiod', 'type', 'courseid',
+                'message', 'messagesubject', 'attachment', 'notification', 'status', 'nextcron'));
+
+        $criteria = new backup_nested_element('criteria');
+        $criterion = new backup_nested_element('criterion', array('id'), array('badgeid',
+                'criteriatype', 'method'));
+
+        $parameters = new backup_nested_element('parameters');
+        $parameter = new backup_nested_element('parameter', array('id'), array('critid',
+                'name', 'value', 'criteriatype'));
+
+        // Build the tree.
+
+        $badges->add_child($badge);
+        $badge->add_child($criteria);
+        $criteria->add_child($criterion);
+        $criterion->add_child($parameters);
+        $parameters->add_child($parameter);
+
+        // Define sources.
+
+        $badge->set_source_table('badge', array('courseid' => backup::VAR_COURSEID));
+        $criterion->set_source_table('badge_criteria', array('badgeid' => backup::VAR_PARENTID));
+
+        $parametersql = 'SELECT cp.*, c.criteriatype
+                             FROM {badge_criteria_param} cp JOIN {badge_criteria} c
+                                 ON cp.critid = c.id
+                             WHERE critid = :critid';
+        $parameterparams = array('critid' => backup::VAR_PARENTID);
+        $parameter->set_source_sql($parametersql, $parameterparams);
+
+        // Define id annotations.
+
+        $badge->annotate_ids('user', 'usercreated');
+        $badge->annotate_ids('user', 'usermodified');
+        $criterion->annotate_ids('badge', 'badgeid');
+        $parameter->annotate_ids('criterion', 'critid');
+        $badge->annotate_files('badges', 'badgeimage', 'id');
+
+        // Return the root element ($badges).
+        return $badges;
+    }
+}
+
 /**
  * structure step in charge of constructing the calender.xml file for all the events found
  * in a given context
index f4a2d46..48fd4e8 100644 (file)
@@ -66,6 +66,13 @@ class restore_final_task extends restore_task {
             $this->add_step(new restore_course_completion_structure_step('course_completion', 'completion.xml'));
         }
 
+        // Conditionally restore course badges.
+        if ($this->get_setting_value('badges') &&
+            $this->get_target() !== backup::TARGET_CURRENT_ADDING &&
+            $this->get_target() !== backup::TARGET_EXISTING_ADDING) {
+            $this->add_step(new restore_badges_structure_step('course_badges', 'badges.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'));
index a0b90b8..b9630a5 100644 (file)
@@ -181,6 +181,19 @@ class restore_root_task extends restore_task {
         $this->add_setting($comments);
         $users->add_dependency($comments);
 
+        // Define badges (dependent of activities).
+        $defaultvalue = false;                      // Safer default.
+        $changeable = false;
+        if (isset($rootsettings['badges']) && $rootsettings['badges']) { // Only enabled when available.
+            $defaultvalue = true;
+            $changeable = true;
+        }
+        $badges = new restore_badges_setting('badges', base_setting::IS_BOOLEAN, $defaultvalue);
+        $badges->set_ui(new backup_setting_ui_checkbox($badges, get_string('rootsettingbadges', 'backup')));
+        $badges->get_ui()->set_changeable($changeable);
+        $this->add_setting($badges);
+        $activities->add_dependency($badges);
+
         // Define Calendar events (dependent of users)
         $defaultvalue = false;                      // Safer default
         $changeable = false;
index 59c09e1..9568637 100644 (file)
@@ -63,6 +63,12 @@ class restore_activities_setting extends restore_generic_setting {}
  */
 class restore_comments_setting extends restore_role_assignments_setting {}
 
+/**
+ * root setting to control if restore will create badges or not,
+ * depends on @restore_activities_setting
+ */
+class restore_badges_setting extends restore_generic_setting {}
+
 /**
  * root setting to control if restore will create
  * events or no, depends of @restore_users_setting
index 8797ee5..a40b104 100644 (file)
@@ -633,7 +633,7 @@ class restore_load_included_files extends restore_structure_step {
         // TODO: qtype_xxx should be replaced by proper backup_qtype_plugin::get_components_and_fileareas() use,
         //       but then we'll need to change it to load plugins itself (because this is executed too early in restore)
         $isfileref   = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'fileref', $data->id);
-        $iscomponent = ($data->component == 'user' || $data->component == 'group' ||
+        $iscomponent = ($data->component == 'user' || $data->component == 'group' || $data->component == 'badges' ||
                         $data->component == 'grouping' || $data->component == 'grade' ||
                         $data->component == 'question' || substr($data->component, 0, 5) == 'qtype');
         if ($isfileref || $iscomponent) {
@@ -1955,6 +1955,153 @@ class restore_comments_structure_step extends restore_structure_step {
     }
 }
 
+/**
+ * This structure steps restores the badges and their configs
+ */
+class restore_badges_structure_step extends restore_structure_step {
+
+    /**
+     * Conditionally decide if this step should be executed.
+     *
+     * This function checks the following parameters:
+     *
+     *   1. Badges and course badges are enabled on the site.
+     *   2. The course/badges.xml file exists.
+     *   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 is badges and course level badges are enabled on this site.
+        if (empty($CFG->enablebadges) || empty($CFG->badges_allowcoursebadges)) {
+            // Disabled, don't restore course badges.
+            return false;
+        }
+
+        // Check if badges.xml 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 badges.
+            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;
+    }
+
+    protected function define_structure() {
+        $paths = array();
+        $paths[] = new restore_path_element('badge', '/badges/badge');
+        $paths[] = new restore_path_element('criterion', '/badges/badge/criteria/criterion');
+        $paths[] = new restore_path_element('parameter', '/badges/badge/criteria/criterion/parameters/parameter');
+
+        return $paths;
+    }
+
+    public function process_badge($data) {
+        global $DB, $CFG;
+
+        require_once $CFG->libdir . '/badgeslib.php';
+
+        $data = (object)$data;
+        $data->usercreated = $this->get_mappingid('user', $data->usercreated);
+        $data->usermodified = $this->get_mappingid('user', $data->usermodified);
+
+        // We'll restore the badge image.
+        $restorefiles = true;
+
+        $courseid = $this->get_courseid();
+
+        $params = array(
+                'name'           => $data->name,
+                'description'    => $data->description,
+                'image'          => 0,
+                'timecreated'    => $this->apply_date_offset($data->timecreated),
+                'timemodified'   => $this->apply_date_offset($data->timemodified),
+                'usercreated'    => $data->usercreated,
+                'usermodified'   => $data->usermodified,
+                'issuername'     => $data->issuername,
+                'issuerurl'      => $data->issuerurl,
+                'issuercontact'  => $data->issuercontact,
+                'expiredate'     => $this->apply_date_offset($data->expiredate),
+                'expireperiod'   => $data->expireperiod,
+                'type'           => BADGE_TYPE_COURSE,
+                'courseid'       => $courseid,
+                'message'        => $data->message,
+                'messagesubject' => $data->messagesubject,
+                'attachment'     => $data->attachment,
+                'notification'   => $data->notification,
+                'status'         => BADGE_STATUS_INACTIVE,
+                'nextcron'       => $this->apply_date_offset($data->nextcron)
+        );
+
+        $newid = $DB->insert_record('badge', $params);
+        $this->set_mapping('badge', $data->id, $newid, $restorefiles);
+    }
+
+    public function process_criterion($data) {
+        global $DB;
+
+        $data = (object)$data;
+
+        $params = array(
+                'badgeid'      => $this->get_new_parentid('badge'),
+                'criteriatype' => $data->criteriatype,
+                'method'       => $data->method
+        );
+        $newid = $DB->insert_record('badge_criteria', $params);
+        $this->set_mapping('criterion', $data->id, $newid);
+    }
+
+    public function process_parameter($data) {
+        global $DB, $CFG;
+        require_once $CFG->libdir . '/badgeslib.php';
+
+        $data = (object)$data;
+        $criteriaid = $this->get_new_parentid('criterion');
+
+        // Parameter array that will go to database.
+        $params = array();
+        $params['critid'] = $criteriaid;
+
+        $oldparam = explode('_', $data->name);
+
+        if ($data->criteriatype == BADGE_CRITERIA_TYPE_ACTIVITY) {
+            $module = $this->get_mappingid('course_module', $oldparam[1]);
+            $params['name'] = $oldparam[0] . '_' . $module;
+            $params['value'] = $oldparam[0] == 'module' ? $module : $data->value;
+        } else if ($data->criteriatype == BADGE_CRITERIA_TYPE_COURSE) {
+            $params['name'] = $oldparam[0] . '_' . $this->get_courseid();
+            $params['value'] = $oldparam[0] == 'course' ? $this->get_courseid() : $data->value;
+        } else if ($data->criteriatype == BADGE_CRITERIA_TYPE_MANUAL) {
+            $params['name'] = $data->name;
+            $params['value'] = $data->value;
+        }
+
+        if (!$DB->record_exists('badge_criteria_param', $params)) {
+            $DB->insert_record('badge_criteria_param', $params);
+        }
+    }
+
+    protected function after_execute() {
+        // Add related files.
+        $this->add_related_files('badges', 'badgeimage', 'badge');
+    }
+}
+
 /**
  * This structure steps restores the calendar events
  */
index 605b9bb..085fe22 100644 (file)
@@ -482,6 +482,7 @@ abstract class backup_controller_dbops extends backup_dbops {
             'backup_general_blocks'             => 'blocks',
             'backup_general_filters'            => 'filters',
             'backup_general_comments'           => 'comments',
+            'backup_general_badges'             => 'badges',
             'backup_general_userscompletion'    => 'userscompletion',
             'backup_general_logs'               => 'logs',
             'backup_general_histories'          => 'grade_histories'
index 0872c37..e90125d 100644 (file)
@@ -383,6 +383,7 @@ abstract class backup_cron_automated_helper {
                 'blocks' => 'backup_auto_blocks',
                 'filters' => 'backup_auto_filters',
                 'comments' => 'backup_auto_comments',
+                'badges' => 'backup_auto_badges',
                 'completion_information' => 'backup_auto_userscompletion',
                 'logs' => 'backup_auto_logs',
                 'histories' => 'backup_auto_histories'
index 66c8a2f..e28d46e 100644 (file)
@@ -79,6 +79,7 @@ $string['choosefilefromactivitybackup_help'] = 'When backup activities using def
 $string['choosefilefromautomatedbackup'] = 'Automated backups';
 $string['choosefilefromautomatedbackup_help'] = 'Contains automatically generated backups.';
 $string['configgeneralactivities'] = 'Sets the default for including activities in a backup.';
+$string['configgeneralbadges'] = 'Sets the default for including badges in a backup.';
 $string['configgeneralanonymize'] = 'If enabled all information pertaining to users will be anonymised by default.';
 $string['configgeneralblocks'] = 'Sets the default for including blocks in a backup.';
 $string['configgeneralcomments'] = 'Sets the default for including comments in a backup.';
@@ -128,6 +129,7 @@ $string['filereferencesnotsamesite'] = 'Backup is from other site, file referenc
 $string['generalactivities'] = 'Include activities';
 $string['generalanonymize'] = 'Anonymise information';
 $string['generalbackdefaults'] = 'General backup defaults';
+$string['generalbadges'] = 'Include badges';
 $string['generalblocks'] = 'Include blocks';
 $string['generalcomments'] = 'Include comments';
 $string['generalfilters'] = 'Include filters';
@@ -218,6 +220,7 @@ $string['rootsettingusers'] = 'Include enrolled users';
 $string['rootsettinganonymize'] = 'Anonymize user information';
 $string['rootsettingroleassignments'] = 'Include user role assignments';
 $string['rootsettingactivities'] = 'Include activities';
+$string['rootsettingbadges'] = 'Include badges';
 $string['rootsettingblocks'] = 'Include blocks';
 $string['rootsettingfilters'] = 'Include filters';
 $string['rootsettingcomments'] = 'Include comments';