mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-46455 logstore_database: added backup/restore support
This commit is contained in:
parent
ea6c56437a
commit
bcfa51ca41
@ -34,4 +34,67 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* for sharing code between all subplugins.
|
||||
*/
|
||||
abstract class restore_tool_log_logstore_subplugin extends restore_subplugin {
|
||||
|
||||
/**
|
||||
* Process log entries.
|
||||
*
|
||||
* This method proceeds to read, complete, remap and, finally,
|
||||
* discard or save every log entry.
|
||||
*
|
||||
* @param array $data log entry.
|
||||
* @return object|null $dataobject A data object with values for one or more fields in the record,
|
||||
* or null if we are not going to process the log.
|
||||
*/
|
||||
protected function process_log($data) {
|
||||
$data = (object) $data;
|
||||
|
||||
// Complete the information that does not come from backup.
|
||||
if (!$data->contextid = $this->get_mappingid('context', $data->contextid)) {
|
||||
// Something went really wrong, cannot find the context this log belongs to.
|
||||
return;
|
||||
}
|
||||
$context = context::instance_by_id($data->contextid, MUST_EXIST);
|
||||
$data->contextlevel = $context->contextlevel;
|
||||
$data->contextinstanceid = $context->instanceid;
|
||||
$data->courseid = $this->task->get_courseid();
|
||||
|
||||
// Remap users.
|
||||
if (!$data->userid = $this->get_mappingid('user', $data->userid)) {
|
||||
// Something went really wrong, cannot find the user this log belongs to.
|
||||
return;
|
||||
}
|
||||
if (!empty($data->relateduserid)) { // This is optional.
|
||||
if (!$data->relateduserid = $this->get_mappingid('user', $data->relateduserid)) {
|
||||
// Something went really wrong, cannot find the relateduserid this log is about.
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!empty($data->realuserid)) { // This is optional.
|
||||
if (!$data->realuserid = $this->get_mappingid('user', $data->realuserid)) {
|
||||
// Something went really wrong, cannot find the realuserid this log is logged in as.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Roll dates.
|
||||
$data->timecreated = $this->apply_date_offset($data->timecreated);
|
||||
|
||||
// Revert other to its original php way.
|
||||
$data->other = unserialize(base64_decode($data->other));
|
||||
|
||||
// Arrived here, we have both 'objectid' and 'other' to be converted. This is the tricky part.
|
||||
// Both are pointing to other records id, but the sources are not identified in the
|
||||
// same way restore mappings work. So we need to delegate them to some resolver that
|
||||
// will give us the correct restore mapping to be used.
|
||||
if (!empty($data->objectid)) {
|
||||
// TODO: Call to the resolver.
|
||||
return;
|
||||
}
|
||||
if (!empty($data->other)) {
|
||||
// TODO: Call to the resolver.
|
||||
return;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Backup implementation for the (tool_log) logstore_database subplugin.
|
||||
*
|
||||
* @package logstore_database
|
||||
* @category backup
|
||||
* @copyright 2015 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
class backup_logstore_database_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_database_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);
|
||||
|
||||
// Get the details for the external database.
|
||||
$manager = new \tool_log\log\manager();
|
||||
$store = new \logstore_database\log\store($manager);
|
||||
$extdb = $store->get_extdb();
|
||||
|
||||
if (!$extdb) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$subpluginlog->set_source_db($extdb);
|
||||
$subpluginlog->set_source_table($store->get_config_value('dbtable'), array('contextid' => backup::VAR_CONTEXTID));
|
||||
|
||||
return $subplugin;
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Restore implementation for the (tool_log) logstore_database subplugin.
|
||||
*
|
||||
* @package logstore_database
|
||||
* @category backup
|
||||
* @copyright 2015 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
class restore_logstore_database_subplugin extends restore_tool_log_logstore_subplugin {
|
||||
|
||||
/**
|
||||
* @var moodle_database the external database.
|
||||
*/
|
||||
private static $extdb = null;
|
||||
|
||||
/**
|
||||
* @var string the external database table name.
|
||||
*/
|
||||
private static $extdbtablename = null;
|
||||
|
||||
/**
|
||||
* The constructor for this logstore.
|
||||
*
|
||||
* @param string $subplugintype the subplugin type.
|
||||
* @param string $subpluginname the subplugin name.
|
||||
* @param restore_structure_step $step.
|
||||
*/
|
||||
public function __construct($subplugintype, $subpluginname, $step) {
|
||||
// Check that the logstore is enabled before setting variables.
|
||||
$enabledlogstores = explode(',', get_config('tool_log', 'enabled_stores'));
|
||||
if (in_array('logstore_database', $enabledlogstores)) {
|
||||
$manager = new \tool_log\log\manager();
|
||||
$store = new \logstore_database\log\store($manager);
|
||||
self::$extdb = $store->get_extdb();
|
||||
self::$extdbtablename = $store->get_config_value('dbtable');
|
||||
}
|
||||
|
||||
parent::__construct($subplugintype, $subpluginname, $step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subplugin structure to attach to the 'logstore' XML element.
|
||||
*
|
||||
* @return restore_path_element[] array of elements to be processed on restore.
|
||||
*/
|
||||
protected function define_logstore_subplugin_structure() {
|
||||
// If the logstore is not enabled we don't add structures for it.
|
||||
$enabledlogstores = explode(',', get_config('tool_log', 'enabled_stores'));
|
||||
if (!in_array('logstore_database', $enabledlogstores)) {
|
||||
return array(); // The logstore is not enabled, nothing to restore.
|
||||
}
|
||||
|
||||
$paths = array();
|
||||
|
||||
$elename = $this->get_namefor('log');
|
||||
$elepath = $this->get_pathfor('/logstore_database_log');
|
||||
$paths[] = new restore_path_element($elename, $elepath);
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process logstore_database_log entries.
|
||||
*
|
||||
* This method proceeds to read, complete, remap and, finally,
|
||||
* discard or save every log entry.
|
||||
*
|
||||
* @param array() $data log entry.
|
||||
* @return null if we are not restoring the log.
|
||||
*/
|
||||
public function process_logstore_database_log($data) {
|
||||
// Do not bother processing if we can not add it to a database.
|
||||
if (!self::$extdb || !self::$extdbtablename) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this->process_log($data);
|
||||
|
||||
if ($data) {
|
||||
self::$extdb->insert_record(self::$extdbtablename, $data);
|
||||
}
|
||||
}
|
||||
}
|
@ -258,6 +258,30 @@ class store implements \tool_log\log\writer, \core\log\sql_reader {
|
||||
return $this->extdb->count_records_select($dbtable, $selectwhere, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a config value for the store.
|
||||
*
|
||||
* @param string $name Config name
|
||||
* @param mixed $default default value
|
||||
* @return mixed config value if set, else the default value.
|
||||
*/
|
||||
public function get_config_value($name, $default = null) {
|
||||
return $this->get_config($name, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the external database object.
|
||||
*
|
||||
* @return \moodle_database $extdb
|
||||
*/
|
||||
public function get_extdb() {
|
||||
if (!$this->init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->extdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are the new events appearing in the reader?
|
||||
*
|
||||
|
@ -60,56 +60,10 @@ class restore_logstore_standard_subplugin extends restore_tool_log_logstore_subp
|
||||
public function process_logstore_standard_log($data) {
|
||||
global $DB;
|
||||
|
||||
$data = (object)$data;
|
||||
$data = $this->process_log($data);
|
||||
|
||||
// Complete the information that does not come from backup.
|
||||
if (! $data->contextid = $this->get_mappingid('context', $data->contextid)) {
|
||||
// Something went really wrong, cannot find the context this log belongs to.
|
||||
return;
|
||||
if ($data) {
|
||||
$DB->insert_record('logstore_standard_log', $data);
|
||||
}
|
||||
$context = context::instance_by_id($data->contextid, MUST_EXIST);
|
||||
$data->contextlevel = $context->contextlevel;
|
||||
$data->contextinstanceid = $context->instanceid;
|
||||
$data->courseid = $this->task->get_courseid();
|
||||
|
||||
// Remap users.
|
||||
if (! $data->userid = $this->get_mappingid('user', $data->userid)) {
|
||||
// Something went really wrong, cannot find the user this log belongs to.
|
||||
return;
|
||||
}
|
||||
if (!empty($data->relateduserid)) { // This is optional.
|
||||
if (! $data->relateduserid = $this->get_mappingid('user', $data->relateduserid)) {
|
||||
// Something went really wrong, cannot find the relateduserid this log is about.
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!empty($data->realuserid)) { // This is optional.
|
||||
if (! $data->realuserid = $this->get_mappingid('user', $data->realuserid)) {
|
||||
// Something went really wrong, cannot find the realuserid this log is logged in as.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Roll dates.
|
||||
$data->timecreated = $this->apply_date_offset($data->timecreated);
|
||||
|
||||
// Revert other to its original php way.
|
||||
$data->other = unserialize(base64_decode($data->other));
|
||||
|
||||
// Arrived here, we have both 'objectid' and 'other' to be converted. This is the tricky part.
|
||||
// Both are pointing to other records id, but the sources are not identified in the
|
||||
// same way restore mappings work. So we need to delegate them to some resolver that
|
||||
// will give us the correct restore mapping to be used.
|
||||
if (!empty($data->objectid)) {
|
||||
// TODO: Call to the resolver.
|
||||
return;
|
||||
}
|
||||
if (!empty($data->other)) {
|
||||
// TODO: Call to the resolver.
|
||||
return;
|
||||
}
|
||||
|
||||
// Arrived here, everything is now ready to be added to database, let's proceed.
|
||||
$DB->insert_record('logstore_standard_log', $data);
|
||||
}
|
||||
}
|
||||
|
@ -33,11 +33,11 @@
|
||||
abstract class backup_structure_dbops extends backup_dbops {
|
||||
|
||||
public static function get_iterator($element, $params, $processor) {
|
||||
global $DB;
|
||||
// Check we are going to get_iterator for one backup_nested_element
|
||||
if (! $element instanceof backup_nested_element) {
|
||||
throw new base_element_struct_exception('backup_nested_element_expected');
|
||||
}
|
||||
|
||||
// If var_array, table and sql are null, and element has no final elements it is one nested element without source
|
||||
// Just return one 1 element iterator without information
|
||||
if ($element->get_source_array() === null && $element->get_source_table() === null &&
|
||||
@ -48,10 +48,10 @@ abstract class backup_structure_dbops extends backup_dbops {
|
||||
return new backup_array_iterator($element->get_source_array());
|
||||
|
||||
} else if ($element->get_source_table() !== null) { // It's one table, return recordset iterator
|
||||
return $DB->get_recordset($element->get_source_table(), self::convert_params_to_values($params, $processor), $element->get_source_table_sortby());
|
||||
return $element->get_source_db()->get_recordset($element->get_source_table(), self::convert_params_to_values($params, $processor), $element->get_source_table_sortby());
|
||||
|
||||
} else if ($element->get_source_sql() !== null) { // It's one sql, return recordset iterator
|
||||
return $DB->get_recordset_sql($element->get_source_sql(), self::convert_params_to_values($params, $processor));
|
||||
return $element->get_source_db()->get_recordset_sql($element->get_source_sql(), self::convert_params_to_values($params, $processor));
|
||||
|
||||
} else { // No sources, supress completely, using null iterator
|
||||
return new backup_null_iterator();
|
||||
|
@ -41,6 +41,11 @@ class backup_nested_element extends base_nested_element implements processable {
|
||||
protected $results; // Logs the results we encounter during the process.
|
||||
protected $logs; // Some log messages that could be retrieved later.
|
||||
|
||||
/**
|
||||
* @var \moodle_database $dbtouse
|
||||
*/
|
||||
protected $dbtouse;
|
||||
|
||||
/**
|
||||
* Constructor - instantiates one backup_nested_element, specifying its basic info.
|
||||
*
|
||||
@ -49,6 +54,8 @@ class backup_nested_element extends base_nested_element implements processable {
|
||||
* @param array $final_elements this element will handle (optional, defaults to null)
|
||||
*/
|
||||
public function __construct($name, $attributes = null, $final_elements = null) {
|
||||
global $DB;
|
||||
|
||||
parent::__construct($name, $attributes, $final_elements);
|
||||
$this->var_array = null;
|
||||
$this->table = null;
|
||||
@ -61,6 +68,7 @@ class backup_nested_element extends base_nested_element implements processable {
|
||||
$this->counter = 0;
|
||||
$this->results = array();
|
||||
$this->logs = array();
|
||||
$this->dbtouse = $DB;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -193,6 +201,15 @@ class backup_nested_element extends base_nested_element implements processable {
|
||||
$this->var_array = $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database we want to use.
|
||||
*
|
||||
* @param \moodle_database $db
|
||||
*/
|
||||
public function set_source_db($db) {
|
||||
$this->dbtouse = $db;
|
||||
}
|
||||
|
||||
public function set_source_table($table, $params, $sortby = null) {
|
||||
if (!is_array($params)) { // Check we are passing array
|
||||
throw new base_element_struct_exception('setsourcerequiresarrayofparams');
|
||||
@ -260,6 +277,15 @@ class backup_nested_element extends base_nested_element implements processable {
|
||||
return $this->var_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database we want to use.
|
||||
*
|
||||
* @return \moodle_database $db
|
||||
*/
|
||||
public function get_source_db() {
|
||||
return $this->dbtouse;
|
||||
}
|
||||
|
||||
public function get_source_table() {
|
||||
return $this->table;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user