From 73c2a354202c7f280bf06d0aacc8db7930a002ff Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sun, 29 Mar 2015 16:53:07 +0200 Subject: [PATCH] MDL-46455 backup: Implement backup of standard logstore Using standard subplugin support, this commit implements the backup of logstore subplugins in general and the standard logstore in particular. Notes: - Uses a custom final element (base64_encode_final_element) to support the storage of serialized 'other' information in logs. - Organization: Instead of directly extending backup_subplugin, every logstore extends backup_tool_log_logstore_subplugin just in case any shared code is needed in the future. - Implements both course and activity logs, sharing the structure completely (both are based in contextid to pick the target information, from database or whatever other logstores use). --- ...ckup_tool_log_logstore_subplugin.class.php | 37 +++++++++++++ ...ckup_logstore_standard_subplugin.class.php | 55 +++++++++++++++++++ backup/moodle2/backup_activity_task.class.php | 3 + backup/moodle2/backup_course_task.class.php | 3 + backup/moodle2/backup_custom_fields.php | 19 +++++++ backup/moodle2/backup_stepslib.php | 30 ++++++++++ 6 files changed, 147 insertions(+) create mode 100644 admin/tool/log/backup/moodle2/backup_tool_log_logstore_subplugin.class.php create mode 100644 admin/tool/log/store/standard/backup/moodle2/backup_logstore_standard_subplugin.class.php diff --git a/admin/tool/log/backup/moodle2/backup_tool_log_logstore_subplugin.class.php b/admin/tool/log/backup/moodle2/backup_tool_log_logstore_subplugin.class.php new file mode 100644 index 00000000000..b86e92aca0e --- /dev/null +++ b/admin/tool/log/backup/moodle2/backup_tool_log_logstore_subplugin.class.php @@ -0,0 +1,37 @@ +. + +/** + * Backup support for tool_log logstore subplugins. + * + * @package tool_log + * @category backup + * @copyright 2015 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(); + +/** + * Parent class of all the logstore subplugin implementations. + * + * Note: While this intermediate class is not strictly required and all the + * subplugin implementations can extend directly {@link backup_subplugin}, + * it is always recommended to have it, both for better testing and also + * for sharing code between all subplugins. + */ +abstract class backup_tool_log_logstore_subplugin extends backup_subplugin { +} diff --git a/admin/tool/log/store/standard/backup/moodle2/backup_logstore_standard_subplugin.class.php b/admin/tool/log/store/standard/backup/moodle2/backup_logstore_standard_subplugin.class.php new file mode 100644 index 00000000000..32db1b8f7da --- /dev/null +++ b/admin/tool/log/store/standard/backup/moodle2/backup_logstore_standard_subplugin.class.php @@ -0,0 +1,55 @@ +. + +/** + * Backup implementation for the (tool_log) logstore_standard subplugin. + * + * @package logstore_standard + * @category backup + * @copyright 2015 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(); + +class backup_logstore_standard_subplugin extends backup_tool_log_logstore_subplugin { + + /** + * Returns the subplugin structure to attach to the 'logstore' XML element. + * + * @return backup_subplugin_element the subplugin structure to be attached. + */ + protected function define_logstore_subplugin_structure() { + + $subplugin = $this->get_subplugin_element(); + $subpluginwrapper = new backup_nested_element($this->get_recommended_name()); + + // Create the custom (base64 encoded, xml safe) 'other' final element. + $otherelement = new base64_encode_final_element('other'); + + $subpluginlog = new backup_nested_element('logstore_standard_log', array('id'), array( + 'eventname', 'component', 'action', 'target', 'objecttable', + 'objectid', 'crud', 'edulevel', 'contextid', 'userid', 'relateduserid', + 'anonymous', $otherelement, 'timecreated', 'ip', 'realuserid')); + + $subplugin->add_child($subpluginwrapper); + $subpluginwrapper->add_child($subpluginlog); + + $subpluginlog->set_source_table('logstore_standard_log', array('contextid' => backup::VAR_CONTEXTID)); + + return $subplugin; + } +} diff --git a/backup/moodle2/backup_activity_task.class.php b/backup/moodle2/backup_activity_task.class.php index 8eac1691d29..5c47f36e4dd 100644 --- a/backup/moodle2/backup_activity_task.class.php +++ b/backup/moodle2/backup_activity_task.class.php @@ -166,7 +166,10 @@ abstract class backup_activity_task extends backup_task { // Generate the logs file (conditionally) if ($this->get_setting_value('logs')) { + // Legacy logs. $this->add_step(new backup_activity_logs_structure_step('activity_logs', 'logs.xml')); + // New log stores. + $this->add_step(new backup_activity_logstores_structure_step('activity_logstores', 'logstores.xml')); } // Generate the calendar events file (conditionally) diff --git a/backup/moodle2/backup_course_task.class.php b/backup/moodle2/backup_course_task.class.php index c7b64b4c287..7ac637cbebe 100644 --- a/backup/moodle2/backup_course_task.class.php +++ b/backup/moodle2/backup_course_task.class.php @@ -121,7 +121,10 @@ class backup_course_task extends backup_task { // Generate the logs file (conditionally) if ($this->get_setting_value('logs')) { + // Legacy logs. $this->add_step(new backup_course_logs_structure_step('course_logs', 'logs.xml')); + // New log stores. + $this->add_step(new backup_course_logstores_structure_step('course_logstores', 'logstores.xml')); } // Generate the inforef file (must be after ALL steps gathering annotations of ANY type) diff --git a/backup/moodle2/backup_custom_fields.php b/backup/moodle2/backup_custom_fields.php index b5c32a5e84b..b2170984735 100644 --- a/backup/moodle2/backup_custom_fields.php +++ b/backup/moodle2/backup_custom_fields.php @@ -78,6 +78,25 @@ class mnethosturl_final_element extends backup_final_element { } } +/** + * Implementation of {@link backup_final_element} that provides base64 encoding. + * + * This final element transparently encodes with base64_encode() contents that + * normally are not safe for being stored in utf-8 xml files (binaries, serialized + * data...). + */ +class base64_encode_final_element extends backup_final_element { + + /** + * Set the value for the final element, encoding it as utf-8/xml safe base64. + * + * @param string $value Original value coming from backup step source, usually db. + */ + public function set_value($value) { + parent::set_value(base64_encode($value)); + } +} + /** * Implementation of backup_nested_element that provides special handling of files * diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index 4246b927fc9..436f19f36dd 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -1485,6 +1485,36 @@ class backup_activity_logs_structure_step extends backup_structure_step { } } +/** + * Structure step in charge of constructing the logstores.xml file for the course logs. + * + * This backup step will backup the logs for all the enabled logstore subplugins supporting + * it, for logs belonging to the course level. + */ +class backup_course_logstores_structure_step extends backup_structure_step { + + protected function define_structure() { + + // Define the structure of logstores container. + $logstores = new backup_nested_element('logstores'); + $logstore = new backup_nested_element('logstore'); + $logstores->add_child($logstore); + + // Add the tool_log logstore subplugins information to the logstore element. + $this->add_subplugin_structure('logstore', $logstore, true, 'tool', 'log'); + + return $logstores; + } +} + +/** + * Structure step in charge of constructing the logstores.xml file for the activity logs. + * + * Note: Activity structure is completely equivalent to the course one, so just extend it. + */ +class backup_activity_logstores_structure_step extends backup_course_logstores_structure_step { +} + /** * structure in charge of constructing the inforef.xml file for all the items we want * to have referenced there (users, roles, files...)