diff --git a/mod/data/backup/moodle2/backup_data_activity_task.class.php b/mod/data/backup/moodle2/backup_data_activity_task.class.php new file mode 100644 index 00000000000..e0802e75b5d --- /dev/null +++ b/mod/data/backup/moodle2/backup_data_activity_task.class.php @@ -0,0 +1,75 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->dirroot . '/mod/data/backup/moodle2/backup_data_stepslib.php'); // Because it exists (must) + +/** + * data backup task that provides all the settings and steps to perform one + * complete backup of the activity + */ +class backup_data_activity_task extends backup_activity_task { + + /** + * Define (add) particular settings this activity can have + */ + protected function define_my_settings() { + // No particular settings for this activity + } + + /** + * Define (add) particular steps this activity can have + */ + protected function define_my_steps() { + // Data only has one structure step + $this->add_step(new backup_data_activity_structure_step('data_structure', 'data.xml')); + } + + /** + * Code the transformations to perform in the activity in + * order to get transportable (encoded) links + */ + static public function encode_content_links($content) { + global $CFG; + + $base = preg_quote($CFG->wwwroot,"/"); + + // Link to the list of datas + $search="/(".$base."\/mod\/data\/index.php\?id\=)([0-9]+)/"; + $content= preg_replace($search, '$@DATAINDEX*$2@$', $content); + + // Link to data view by moduleid + $search="/(".$base."\/mod\/data\/view.php\?id\=)([0-9]+)/"; + $content= preg_replace($search, '$@DATAVIEWBYID*$2@$', $content); + + /// Link to database view by databaseid + $search="/(".$base."\/mod\/data\/view.php\?d\=)([0-9]+)/"; + $content= preg_replace($search,'$@DATAVIEWBYD*$2@$', $content); + + /// Link to one "record" of the database + $search="/(".$base."\/mod\/data\/view.php\?d\=)([0-9]+)\&(amp;)rid\=([0-9]+)/"; + $content= preg_replace($search,'$@DATAVIEWRECORD*$2*$4@$', $content); + + return $content; + } +} diff --git a/mod/data/backup/moodle2/backup_data_stepslib.php b/mod/data/backup/moodle2/backup_data_stepslib.php new file mode 100644 index 00000000000..691b0596f75 --- /dev/null +++ b/mod/data/backup/moodle2/backup_data_stepslib.php @@ -0,0 +1,123 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Define all the backup steps that will be used by the backup_data_activity_task + */ + +/** + * Define the complete data structure for backup, with file and id annotations + */ +class backup_data_activity_structure_step extends backup_activity_structure_step { + + protected function define_structure() { + + // To know if we are including userinfo + $userinfo = $this->get_setting_value('userinfo'); + + // Define each element separated + $data = new backup_nested_element('data', array('id'), array( + 'name', 'intro', 'introformat', 'comments', + 'timeavailablefrom', 'timeavailableto', 'timeviewfrom', 'timeviewto', + 'requiredentries', 'requiredentriestoview', 'maxentries', 'rssarticles', + 'singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter', + 'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', + 'jstemplate', 'asearchtemplate', 'approval', 'scale', + 'assessed', 'assesstimestart', 'assesstimefinish', 'defaultsort', + 'defaultsortdir', 'editany', 'notification')); + + $fields = new backup_nested_element('fields'); + + $field = new backup_nested_element('field', array('id'), array( + 'type', 'name', 'description', 'param1', 'param2', + 'param3', 'param4', 'param5', 'param6', + 'param7', 'param8', 'param9', 'param10')); + + $records = new backup_nested_element('records'); + + $record = new backup_nested_element('record', array('id'), array( + 'userid', 'groupid', 'timecreated', 'timemodified', + 'approved')); + + $contents = new backup_nested_element('contents'); + + $content = new backup_nested_element('content', array('id'), array( + 'fieldid', 'content', 'content1', 'content2', + 'content3', 'content4')); + + $ratings = new backup_nested_element('ratings'); + + $rating = new backup_nested_element('rating', array('id'), array( + 'scaleid', 'value', 'userid', 'timecreated', 'timemodified')); + + // Build the tree + $data->add_child($fields); + $fields->add_child($field); + + $data->add_child($records); + $records->add_child($record); + + $record->add_child($contents); + $contents->add_child($content); + + $record->add_child($ratings); + $ratings->add_child($rating); + + // Define sources + $data->set_source_table('data', array('id' => backup::VAR_ACTIVITYID)); + + $field->set_source_sql(' + SELECT * + FROM {data_fields} + WHERE dataid = ?', + array(backup::VAR_PARENTID)); + + // All the rest of elements only happen if we are including user info + if ($userinfo) { + $record->set_source_table('data_records', array('dataid' => backup::VAR_PARENTID)); + + $content->set_source_table('data_content', array('recordid' => backup::VAR_PARENTID)); + + $rating->set_source_table('rating', array('contextid' => backup::VAR_CONTEXTID, + 'itemid' => backup::VAR_PARENTID)); + $rating->set_source_alias('rating', 'value'); + } + + // Define id annotations + $data->annotate_ids('scale', 'scale'); + + $record->annotate_ids('user', 'userid'); + $record->annotate_ids('group', 'groupid'); + + $rating->annotate_ids('scale', 'scaleid'); + $rating->annotate_ids('user', 'userid'); + + // Define file annotations + $data->annotate_files('mod_data', 'intro', null); // This file area hasn't itemid + $content->annotate_files('mod_data', 'content', 'id'); // By content->id + + // Return the root element (data), wrapped into standard activity structure + return $this->prepare_activity_structure($data); + } +} diff --git a/mod/data/backup/moodle2/restore_data_activity_task.class.php b/mod/data/backup/moodle2/restore_data_activity_task.class.php new file mode 100644 index 00000000000..a97c26b0c95 --- /dev/null +++ b/mod/data/backup/moodle2/restore_data_activity_task.class.php @@ -0,0 +1,85 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/data/backup/moodle2/restore_data_stepslib.php'); // Because it exists (must) + +/** + * data restore task that provides all the settings and steps to perform one + * complete restore of the activity + */ +class restore_data_activity_task extends restore_activity_task { + + /** + * Define (add) particular settings this activity can have + */ + protected function define_my_settings() { + // No particular settings for this activity + } + + /** + * Define (add) particular steps this activity can have + */ + protected function define_my_steps() { + // Data only has one structure step + $this->add_step(new restore_data_activity_structure_step('data_structure', 'data.xml')); + } + + /** + * Define the contents in the activity that must be + * processed by the link decoder + */ + static public function define_decode_contents() { + $contents = array(); + + $contents[] = new restore_decode_content('data', array( + 'intro', 'singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter', + 'addtemplate', 'rsstemplate', 'rsstitletemplate', 'asearchtemplate'), 'data'); + $contents[] = new restore_decode_content('data_fields', array( + 'description', 'param1', 'param2', 'param3', + 'param4', 'param5', 'param6', 'param7', + 'param8', 'param9', 'param10'), 'data_field'); + $contents[] = new restore_decode_content('data_content', array( + 'content', 'content1', 'content2', 'content3', 'content4')); + + return $contents; + } + + /** + * Define the decoding rules for links belonging + * to the activity to be executed by the link decoder + */ + static public function define_decode_rules() { + $rules = array(); + + $rules[] = new restore_decode_rule('DATAVIEWBYID', '/mod/data/view.php?id=$1', 'course_module'); + $rules[] = new restore_decode_rule('DATAVIEWBYD', '/mod/data/index.php?d=$1', 'data'); + $rules[] = new restore_decode_rule('DATAINDEX', '/mod/data/index.php?id=$1', 'course'); + $rules[] = new restore_decode_rule('DATAVIEWRECORD', '/mod/data/view.php?d=$1&rid=$2', array('data', 'data_record')); + + return $rules; + + } +} diff --git a/mod/data/backup/moodle2/restore_data_stepslib.php b/mod/data/backup/moodle2/restore_data_stepslib.php new file mode 100644 index 00000000000..b89955cdc91 --- /dev/null +++ b/mod/data/backup/moodle2/restore_data_stepslib.php @@ -0,0 +1,151 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Define all the restore steps that will be used by the restore_data_activity_task + */ + +/** + * Structure step to restore one data activity + */ +class restore_data_activity_structure_step extends restore_activity_structure_step { + + protected function define_structure() { + + $paths = array(); + $userinfo = $this->get_setting_value('userinfo'); + + $paths[] = new restore_path_element('data', '/activity/data'); + $paths[] = new restore_path_element('data_field', '/activity/data/fields/field'); + if ($userinfo) { + $paths[] = new restore_path_element('data_record', '/activity/data/records/record'); + $paths[] = new restore_path_element('data_content', '/activity/data/records/record/contents/content'); + $paths[] = new restore_path_element('data_rating', '/activity/data/records/record/ratings/rating'); + } + + // Return the paths wrapped into standard activity structure + return $this->prepare_activity_structure($paths); + } + + protected function process_data($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + $data->course = $this->get_courseid(); + + $data->timeavailablefrom = $this->apply_date_offset($data->timeavailablefrom); + $data->timeavailableto = $this->apply_date_offset($data->timeavailableto); + $data->timeviewfrom = $this->apply_date_offset($data->timeviewfrom); + $data->timeviewto = $this->apply_date_offset($data->timeviewto); + $data->assesstimestart = $this->apply_date_offset($data->assesstimestart); + $data->assesstimefinish = $this->apply_date_offset($data->assesstimefinish); + + if ($data->scale < 0) { // scale found, get mapping + $data->scale = -($this->get_mappingid('scale', abs($data->scale))); + } + + // insert the data record + $newitemid = $DB->insert_record('data', $data); + $this->apply_activity_instance($newitemid); + } + + protected function process_data_field($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + $data->dataid = $this->get_new_parentid('data'); + + // insert the data_fields record + $newitemid = $DB->insert_record('data_fields', $data); + $this->set_mapping('data_field', $oldid, $newitemid, false); // no files associated + } + + protected function process_data_record($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + $data->timecreated = $this->apply_date_offset($data->timecreated); + $data->timemodified = $this->apply_date_offset($data->timemodified); + + $data->userid = $this->get_mappingid('user', $data->userid); + $data->groupid = $this->get_mappingid('group', $data->groupid); + $data->dataid = $this->get_new_parentid('data'); + + // insert the data_records record + $newitemid = $DB->insert_record('data_records', $data); + $this->set_mapping('data_record', $oldid, $newitemid, false); // no files associated + } + + protected function process_data_content($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + $data->fieldid = $this->get_mappingid('data_field', $data->fieldid); + $data->recordid = $this->get_new_parentid('data_record'); + + // insert the data_content record + $newitemid = $DB->insert_record('data_content', $data); + $this->set_mapping('data_content', $oldid, $newitemid, true); // files by this itemname + } + + protected function process_data_rating($data) { + global $DB; + + $data = (object)$data; + + // Cannot use ratings API, cause, it's missing the ability to specify times (modified/created) + $data->contextid = $this->task->get_contextid(); + $data->itemid = $this->get_new_parentid('data_record'); + if ($data->scaleid < 0) { // scale found, get mapping + $data->scaleid = -($this->get_mappingid('scale', abs($data->scaleid))); + } + $data->rating = $data->value; + $data->userid = $this->get_mappingid('user', $data->userid); + $data->timecreated = $this->apply_date_offset($data->timecreated); + $data->timemodified = $this->apply_date_offset($data->timemodified); + + $newitemid = $DB->insert_record('rating', $data); + } + + protected function after_execute() { + global $DB; + // Add data related files, no need to match by itemname (just internally handled context) + $this->add_related_files('mod_data', 'intro', null); + // Add content related files, matching by itemname (data_content) + $this->add_related_files('mod_data', 'content', 'data_content'); + // Adjust the data->defaultsort field + if ($defaultsort = $DB->get_field('data', 'defaultsort', array('id' => $this->get_new_parentid('data')))) { + if ($defaultsort = $this->get_mappingid('data_field', $defaultsort)) { + $DB->set_field('data', 'defaultsort', $defaultsort, array('id' => $this->get_new_parentid('data'))); + } + } + } +} diff --git a/mod/data/field/textarea/field.class.php b/mod/data/field/textarea/field.class.php index 248834523b4..3a28d57f47e 100755 --- a/mod/data/field/textarea/field.class.php +++ b/mod/data/field/textarea/field.class.php @@ -67,7 +67,7 @@ class data_field_textarea extends data_field_base { $formats[$fid] = $strformats[$fid]; } $editor->use_editor($field, $options); - $str .= '
'; + $str .= '
'; $str .= '