Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Export db content to file.
19
 *
20
 * @package    tool_dbtransfer
21
 * @copyright  2008 Petr Skoda {@link http://skodak.org/}
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
defined('MOODLE_INTERNAL') || die;
26
/*
27
 
28
TODO:
29
  - exporting to server file >2GB fails in 32bit operating systems - needs warning
30
  - we may run out of disk space exporting to server file - we must verify the file is not truncated; read from the end of file?
31
  - when sending file >4GB - FAT32 limit, Apache limit, browser limit - needs warning
32
  - there must be some form of progress bar during export, transfer - new tracking class could be passed around
33
  - command line operation - could work around some 2G/4G limits in PHP; useful for cron full backups
34
  - by default allow exporting into empty database only (no tables with the same prefix yet)
35
  - all dangerous operation (like deleting of all data) should be confirmed by key found in special file in dataroot
36
    (user would need file access to dataroot which might prevent various "accidents")
37
  - implement "Export/import running" notification in lib/setup.php (similar to new upgrade flag in config table)
38
  - gzip compression when storing xml file - the xml is very verbose and full of repeated tags (zip is not suitable here at all)
39
    this could help us keep the files below 2G (expected ratio is > 10:1)
40
 
41
*/
42
 
43
require_once($CFG->libdir.'/adminlib.php');
44
require_once($CFG->libdir.'/dtllib.php');
45
 
46
/**
47
 * Initiate database export.
48
 * @param string $description
49
 * @param moodle_database $mdb
50
 * @return does not return, calls die()
51
 */
52
function tool_dbtransfer_export_xml_database($description, $mdb) {
53
    core_php_time_limit::raise();
54
 
55
    \core\session\manager::write_close(); // Release session.
56
 
57
    header('Content-Type: application/xhtml+xml; charset=utf-8');
58
    header('Content-Disposition: attachment; filename=database.xml');
59
    header('Expires: 0');
60
    header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
61
    header('Pragma: public');
62
 
63
    while(@ob_flush());
64
 
65
    $var = new file_xml_database_exporter('php://output', $mdb);
66
    $var->export_database($description);
67
 
68
    // No more output.
69
    die;
70
}
71
 
72
/**
73
 * Initiate database transfer.
74
 * @param moodle_database $sourcedb
75
 * @param moodle_database $targetdb
76
 * @param progress_trace $feedback
77
 * @return void
78
 */
79
function tool_dbtransfer_transfer_database(moodle_database $sourcedb, moodle_database $targetdb, progress_trace $feedback = null) {
80
    core_php_time_limit::raise();
81
 
82
    \core\session\manager::write_close(); // Release session.
83
 
84
    $var = new database_mover($sourcedb, $targetdb, true, $feedback);
85
    $var->export_database(null);
86
 
87
    tool_dbtransfer_rebuild_target_log_actions($targetdb, $feedback);
88
}
89
 
90
/**
91
 * Very hacky function for rebuilding of log actions in target database.
92
 * @param moodle_database $target
93
 * @param progress_trace $feedback
94
 * @return void
95
 * @throws Exception on conversion error
96
 */
97
function tool_dbtransfer_rebuild_target_log_actions(moodle_database $target, progress_trace $feedback = null) {
98
    global $DB, $CFG;
99
    require_once("$CFG->libdir/upgradelib.php");
100
 
101
    $feedback->output(get_string('convertinglogdisplay', 'tool_dbtransfer'));
102
 
103
    $olddb = $DB;
104
    $DB = $target;
105
    try {
106
        $DB->delete_records('log_display', array('component'=>'moodle'));
107
        log_update_descriptions('moodle');
108
        $plugintypes = core_component::get_plugin_types();
109
        foreach ($plugintypes as $type => $location) {
110
            $plugs = core_component::get_plugin_list($type);
111
            foreach ($plugs as $plug => $fullplug) {
112
                $component = $type.'_'.$plug;
113
                $DB->delete_records('log_display', array('component'=>$component));
114
                log_update_descriptions($component);
115
            }
116
        }
117
    } catch (Exception $e) {
118
        $DB = $olddb;
119
        throw $e;
120
    }
121
    $DB = $olddb;
122
    $feedback->output(get_string('done', 'core_dbtransfer', null), 1);
123
}
124
 
125
/**
126
 * Returns list of fully working database drivers present in system.
127
 * @return array
128
 */
129
function tool_dbtransfer_get_drivers() {
130
    global $CFG;
131
 
132
    $files = new RegexIterator(new DirectoryIterator("$CFG->libdir/dml"), '|^.*_moodle_database\.php$|');
133
    $drivers = array();
134
 
135
    foreach ($files as $file) {
136
        $matches = null;
137
        preg_match('|^([a-z0-9]+)_([a-z]+)_moodle_database\.php$|', $file->getFilename(), $matches);
138
        if (!$matches) {
139
            continue;
140
        }
141
        $dbtype = $matches[1];
142
        $dblibrary = $matches[2];
143
 
144
        if ($dbtype === 'sqlite3') {
145
            // The sqlite3 driver is not fully working yet and should not be returned.
146
            continue;
147
        }
148
 
149
        $targetdb = moodle_database::get_driver_instance($dbtype, $dblibrary, false);
150
        if ($targetdb->driver_installed() !== true) {
151
            continue;
152
        }
153
 
154
        $driver = $dbtype.'/'.$dblibrary;
155
 
156
        $drivers[$driver] = $targetdb->get_name();
157
    };
158
 
159
    return $drivers;
160
}
161
 
162
/**
163
 * Create CLI maintenance file to prevent all access.
164
 */
165
function tool_dbtransfer_create_maintenance_file() {
166
    global $CFG;
167
 
168
    core_shutdown_manager::register_function('tool_dbtransfer_maintenance_callback');
169
 
170
    $options = new stdClass();
171
    $options->trusted = false;
172
    $options->noclean = false;
173
    $options->filter = false;
174
    $options->para = true;
175
    $options->newlines = false;
176
 
177
    $message = format_text(get_string('climigrationnotice', 'tool_dbtransfer'), FORMAT_MARKDOWN, $options);
178
    $message = bootstrap_renderer::early_error_content($message, '', '', array());
179
    $html = <<<OET
180
<!DOCTYPE html>
181
<html>
182
<header><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><header/>
183
<body>$message</body>
184
</html>
185
OET;
186
 
187
    file_put_contents("$CFG->dataroot/climaintenance.html", $html);
188
    @chmod("$CFG->dataroot/climaintenance.html", $CFG->filepermissions);
189
}
190
 
191
/**
192
 * This callback is responsible for unsetting maintenance mode
193
 * if the migration is interrupted.
194
 */
195
function tool_dbtransfer_maintenance_callback() {
196
    global $CFG;
197
 
198
    if (empty($CFG->tool_dbransfer_migration_running)) {
199
        // Migration was finished properly - keep the maintenance file in place.
200
        return;
201
    }
202
 
203
    if (file_exists("$CFG->dataroot/climaintenance.html")) {
204
        // Failed migration, revert to normal site operation.
205
        unlink("$CFG->dataroot/climaintenance.html");
206
        error_log('tool_dbtransfer: Interrupted database migration detected, switching off CLI maintenance mode.');
207
    }
208
}