Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/backup/util/dbops/backup_controller_dbops.class.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00033 abstract class backup_controller_dbops extends backup_dbops {
00034 
00035     public static function save_controller($controller, $checksum) {
00036         global $DB;
00037         // Check we are going to save one backup_controller
00038         if (! $controller instanceof backup_controller) {
00039             throw new backup_controller_exception('backup_controller_expected');
00040         }
00041         // Check checksum is ok. Sounds silly but it isn't ;-)
00042         if (!$controller->is_checksum_correct($checksum)) {
00043             throw new backup_dbops_exception('backup_controller_dbops_saving_checksum_mismatch');
00044         }
00045         // Get all the columns
00046         $rec = new stdclass();
00047         $rec->backupid     = $controller->get_backupid();
00048         $rec->operation    = $controller->get_operation();
00049         $rec->type         = $controller->get_type();
00050         $rec->itemid       = $controller->get_id();
00051         $rec->format       = $controller->get_format();
00052         $rec->interactive  = $controller->get_interactive();
00053         $rec->purpose      = $controller->get_mode();
00054         $rec->userid       = $controller->get_userid();
00055         $rec->status       = $controller->get_status();
00056         $rec->execution    = $controller->get_execution();
00057         $rec->executiontime= $controller->get_executiontime();
00058         $rec->checksum     = $checksum;
00059         // Serialize information
00060         $rec->controller = base64_encode(serialize($controller));
00061         // Send it to DB
00062         if ($recexists = $DB->get_record('backup_controllers', array('backupid' => $rec->backupid))) {
00063             $rec->id = $recexists->id;
00064             $rec->timemodified = time();
00065             $DB->update_record('backup_controllers', $rec);
00066         } else {
00067             $rec->timecreated = time();
00068             $rec->timemodified = 0;
00069             $rec->id = $DB->insert_record('backup_controllers', $rec);
00070         }
00071         return $rec->id;
00072     }
00073 
00074     public static function load_controller($backupid) {
00075         global $DB;
00076         if (! $controllerrec = $DB->get_record('backup_controllers', array('backupid' => $backupid))) {
00077             throw new backup_dbops_exception('backup_controller_dbops_nonexisting');
00078         }
00079         $controller = unserialize(base64_decode($controllerrec->controller));
00080         // Check checksum is ok. Sounds silly but it isn't ;-)
00081         if (!$controller->is_checksum_correct($controllerrec->checksum)) {
00082             throw new backup_dbops_exception('backup_controller_dbops_loading_checksum_mismatch');
00083         }
00084         return $controller;
00085     }
00086 
00087     public static function create_backup_ids_temp_table($backupid) {
00088         self::create_temptable_from_real_table($backupid, 'backup_ids_template', 'backup_ids_temp');
00089     }
00090 
00094     public static function create_temptable_from_real_table($backupid, $realtablename, $temptablename) {
00095         global $CFG, $DB;
00096         $dbman = $DB->get_manager(); // We are going to use database_manager services
00097 
00098         // As far as xmldb objects use a lot of circular references (prev and next) and we aren't destroying
00099         // them at all, that causes one memory leak of about 3M per backup execution, not problematic for
00100         // individual backups but critical for automated (multiple) ones.
00101         // So we are statically caching the xmldb_table definition here to produce the leak "only" once
00102         static $xmldb_tables = array();
00103 
00104         // Not cached, get it
00105         if (!isset($xmldb_tables[$realtablename])) {
00106             // Note: For now we are going to load the realtablename from core lib/db/install.xml
00107             // that way, any change in the "template" will be applied here automatically. If this causes
00108             // too much slow, we can always forget about the template and keep maintained the xmldb_table
00109             // structure inline - manually - here.
00110             // TODO: Right now, loading the whole lib/db/install.xml is "eating" 10M, we should
00111             // change our way here in order to decrease that memory usage
00112             $templatetablename = $realtablename;
00113             $targettablename   = $temptablename;
00114             $xmlfile = $CFG->dirroot . '/lib/db/install.xml';
00115             $xmldb_file = new xmldb_file($xmlfile);
00116             if (!$xmldb_file->fileExists()) {
00117                 throw new ddl_exception('ddlxmlfileerror', null, 'File does not exist');
00118             }
00119             $loaded = $xmldb_file->loadXMLStructure();
00120             if (!$loaded || !$xmldb_file->isLoaded()) {
00121                 throw new ddl_exception('ddlxmlfileerror', null, 'not loaded??');
00122             }
00123             $xmldb_structure = $xmldb_file->getStructure();
00124             $xmldb_table = $xmldb_structure->getTable($templatetablename);
00125             if (is_null($xmldb_table)) {
00126                 throw new ddl_exception('ddlunknowntable', null, 'The table ' . $templatetablename . ' is not defined in file ' . $xmlfile);
00127             }
00128             // Clean prev & next, we are alone
00129             $xmldb_table->setNext(null);
00130             $xmldb_table->setPrevious(null);
00131             // Rename
00132             $xmldb_table->setName($targettablename);
00133             // Cache it
00134             $xmldb_tables[$realtablename] = $xmldb_table;
00135         }
00136         // Arrived here, we have the table always in static cache, get it
00137         $xmldb_table = $xmldb_tables[$realtablename];
00138         // Set default backupid (not needed but this enforce any missing backupid). That's hackery in action!
00139         $xmldb_table->getField('backupid')->setDefault($backupid);
00140 
00141         $dbman->create_temp_table($xmldb_table); // And create it
00142     }
00143 
00144     public static function drop_backup_ids_temp_table($backupid) {
00145         global $DB;
00146         $dbman = $DB->get_manager(); // We are going to use database_manager services
00147 
00148         $targettablename = 'backup_ids_temp';
00149         $table = new xmldb_table($targettablename);
00150         $dbman->drop_temp_table($table); // And drop it
00151     }
00152 
00156     public static function get_courseid_from_type_id($type, $id) {
00157         global $DB;
00158         if ($type == backup::TYPE_1COURSE) {
00159             return $id; // id is the course id
00160 
00161         } else if ($type == backup::TYPE_1SECTION) {
00162             if (! $courseid = $DB->get_field('course_sections', 'course', array('id' => $id))) {
00163                 throw new backup_dbops_exception('course_not_found_for_section', $id);
00164             }
00165             return $courseid;
00166         } else if ($type == backup::TYPE_1ACTIVITY) {
00167             if (! $courseid = $DB->get_field('course_modules', 'course', array('id' => $id))) {
00168                 throw new backup_dbops_exception('course_not_found_for_moduleid', $id);
00169             }
00170             return $courseid;
00171         }
00172     }
00173 
00178     private static function get_activity_backup_information($task) {
00179 
00180         $contentinfo = array(
00181             'moduleid'   => $task->get_moduleid(),
00182             'sectionid'  => $task->get_sectionid(),
00183             'modulename' => $task->get_modulename(),
00184             'title'      => $task->get_name(),
00185             'directory'  => 'activities/' . $task->get_modulename() . '_' . $task->get_moduleid());
00186 
00187         // Now get activity settings
00188         // Calculate prefix to find valid settings
00189         $prefix = basename($contentinfo['directory']);
00190         $settingsinfo = array();
00191         foreach ($task->get_settings() as $setting) {
00192             // Discard ones without valid prefix
00193             if (strpos($setting->get_name(), $prefix) !== 0) {
00194                 continue;
00195             }
00196             // Validate level is correct (activity)
00197             if ($setting->get_level() != backup_setting::ACTIVITY_LEVEL) {
00198                 throw new backup_controller_exception('setting_not_activity_level', $setting);
00199             }
00200             $settinginfo = array(
00201                 'level'    => 'activity',
00202                 'activity' => $prefix,
00203                 'name'     => $setting->get_name(),
00204                 'value'    => $setting->get_value());
00205             $settingsinfo[$setting->get_name()] = (object)$settinginfo;
00206         }
00207         return array($contentinfo, $settingsinfo);
00208     }
00209 
00214     private static function get_section_backup_information($task) {
00215 
00216         $contentinfo = array(
00217             'sectionid'  => $task->get_sectionid(),
00218             'title'      => $task->get_name(),
00219             'directory'  => 'sections/' . 'section_' . $task->get_sectionid());
00220 
00221         // Now get section settings
00222         // Calculate prefix to find valid settings
00223         $prefix = basename($contentinfo['directory']);
00224         $settingsinfo = array();
00225         foreach ($task->get_settings() as $setting) {
00226             // Discard ones without valid prefix
00227             if (strpos($setting->get_name(), $prefix) !== 0) {
00228                 continue;
00229             }
00230             // Validate level is correct (section)
00231             if ($setting->get_level() != backup_setting::SECTION_LEVEL) {
00232                 throw new backup_controller_exception('setting_not_section_level', $setting);
00233             }
00234             $settinginfo = array(
00235                 'level'    => 'section',
00236                 'section'  => $prefix,
00237                 'name'     => $setting->get_name(),
00238                 'value'    => $setting->get_value());
00239             $settingsinfo[$setting->get_name()] = (object)$settinginfo;
00240         }
00241         return array($contentinfo, $settingsinfo);
00242     }
00243 
00248     private static function get_course_backup_information($task) {
00249 
00250         $contentinfo = array(
00251             'courseid'   => $task->get_courseid(),
00252             'title'      => $task->get_name(),
00253             'directory'  => 'course');
00254 
00255         // Now get course settings
00256         // Calculate prefix to find valid settings
00257         $prefix = basename($contentinfo['directory']);
00258         $settingsinfo = array();
00259         foreach ($task->get_settings() as $setting) {
00260             // Discard ones without valid prefix
00261             if (strpos($setting->get_name(), $prefix) !== 0) {
00262                 continue;
00263             }
00264             // Validate level is correct (course)
00265             if ($setting->get_level() != backup_setting::COURSE_LEVEL) {
00266                 throw new backup_controller_exception('setting_not_course_level', $setting);
00267             }
00268             $settinginfo = array(
00269                 'level'    => 'course',
00270                 'name'     => $setting->get_name(),
00271                 'value'    => $setting->get_value());
00272             $settingsinfo[$setting->get_name()] = (object)$settinginfo;
00273         }
00274         return array($contentinfo, $settingsinfo);
00275     }
00276 
00281     private static function get_root_backup_information($task) {
00282 
00283         // Now get root settings
00284         $settingsinfo = array();
00285         foreach ($task->get_settings() as $setting) {
00286             // Validate level is correct (root)
00287             if ($setting->get_level() != backup_setting::ROOT_LEVEL) {
00288                 throw new backup_controller_exception('setting_not_root_level', $setting);
00289             }
00290             $settinginfo = array(
00291                 'level'    => 'root',
00292                 'name'     => $setting->get_name(),
00293                 'value'    => $setting->get_value());
00294             $settingsinfo[$setting->get_name()] = (object)$settinginfo;
00295         }
00296         return array(null, $settingsinfo);
00297     }
00298 
00303     public static function get_moodle_backup_information($backupid) {
00304 
00305         $detailsinfo = array(); // Information details
00306         $contentsinfo= array(); // Information about backup contents
00307         $settingsinfo= array(); // Information about backup settings
00308         $bc = self::load_controller($backupid); // Load controller
00309 
00310         // Details info
00311         $detailsinfo['id'] = $bc->get_id();
00312         $detailsinfo['backup_id'] = $bc->get_backupid();
00313         $detailsinfo['type'] = $bc->get_type();
00314         $detailsinfo['format'] = $bc->get_format();
00315         $detailsinfo['interactive'] = $bc->get_interactive();
00316         $detailsinfo['mode'] = $bc->get_mode();
00317         $detailsinfo['execution'] = $bc->get_execution();
00318         $detailsinfo['executiontime'] = $bc->get_executiontime();
00319         $detailsinfo['userid'] = $bc->get_userid();
00320         $detailsinfo['courseid'] = $bc->get_courseid();
00321 
00322 
00323         // Init content placeholders
00324         $contentsinfo['activities'] = array();
00325         $contentsinfo['sections']   = array();
00326         $contentsinfo['course']     = array();
00327 
00328         // Contents info (extract information from tasks)
00329         foreach ($bc->get_plan()->get_tasks() as $task) {
00330 
00331             if ($task instanceof backup_activity_task) { // Activity task
00332 
00333                 if ($task->get_setting_value('included')) { // Only return info about included activities
00334                     list($contentinfo, $settings) = self::get_activity_backup_information($task);
00335                     $contentsinfo['activities'][] = $contentinfo;
00336                     $settingsinfo = array_merge($settingsinfo, $settings);
00337                 }
00338 
00339             } else if ($task instanceof backup_section_task) { // Section task
00340 
00341                 if ($task->get_setting_value('included')) { // Only return info about included sections
00342                     list($contentinfo, $settings) = self::get_section_backup_information($task);
00343                     $contentsinfo['sections'][] = $contentinfo;
00344                     $settingsinfo = array_merge($settingsinfo, $settings);
00345                 }
00346 
00347             } else if ($task instanceof backup_course_task) { // Course task
00348 
00349                 list($contentinfo, $settings) = self::get_course_backup_information($task);
00350                 $contentsinfo['course'][] = $contentinfo;
00351                 $settingsinfo = array_merge($settingsinfo, $settings);
00352 
00353             } else if ($task instanceof backup_root_task) { // Root task
00354 
00355                 list($contentinfo, $settings) = self::get_root_backup_information($task);
00356                 $settingsinfo = array_merge($settingsinfo, $settings);
00357             }
00358         }
00359 
00360         $bc->destroy(); // Always need to destroy controller to handle circular references
00361 
00362         return array(array((object)$detailsinfo), $contentsinfo, $settingsinfo);
00363     }
00364 
00369     public static function apply_version_and_release() {
00370         global $CFG;
00371 
00372         if ($CFG->backup_version < backup::VERSION) {
00373             set_config('backup_version', backup::VERSION);
00374             set_config('backup_release', backup::RELEASE);
00375         }
00376     }
00377 
00381     public static function backup_includes_mnet_remote_users($backupid) {
00382         global $CFG, $DB;
00383 
00384         $sql = "SELECT COUNT(*)
00385                   FROM {backup_ids_temp} b
00386                   JOIN {user} u ON u.id = b.itemid
00387                  WHERE b.backupid = ?
00388                    AND b.itemname = 'userfinal'
00389                    AND u.mnethostid != ?";
00390         $count = $DB->count_records_sql($sql, array($backupid, $CFG->mnet_localhost_id));
00391         return (int)(bool)$count;
00392     }
00393 
00399     public static function backup_get_original_course_info($courseid) {
00400         global $DB;
00401         return $DB->get_record('course', array('id' => $courseid), 'fullname, shortname, startdate');
00402     }
00403 
00413     public static function apply_config_defaults(backup_controller $controller) {
00414         // Based on the mode of the backup (general, automated, import, hub...)
00415         // decide the action to perform to get defaults loaded
00416         $mode = $controller->get_mode();
00417 
00418         switch ($mode) {
00419             case backup::MODE_GENERAL:
00420                 // Load the general defaults
00421                 self::apply_general_config_defaults($controller);
00422                 break;
00423             case backup::MODE_AUTOMATED:
00424                 // TODO: Move the loading from automatic stuff to here
00425                 break;
00426             default:
00427                 // Nothing to do for other modes (IMPORT/HUB...). Some day we
00428                 // can define defaults (admin UI...) for them if we want to
00429         }
00430     }
00431 
00437     private static function apply_general_config_defaults(backup_controller $controller) {
00438         $settings = array(
00439             // Config name                      => Setting name
00440             'backup_general_users'              => 'users',
00441             'backup_general_anonymize'          => 'anonymize',
00442             'backup_general_role_assignments'   => 'role_assignments',
00443             'backup_general_user_files'         => 'user_files',
00444             'backup_general_activities'         => 'activities',
00445             'backup_general_blocks'             => 'blocks',
00446             'backup_general_filters'            => 'filters',
00447             'backup_general_comments'           => 'comments',
00448             'backup_general_userscompletion'    => 'userscompletion',
00449             'backup_general_logs'               => 'logs',
00450             'backup_general_histories'          => 'grade_histories'
00451         );
00452         $plan = $controller->get_plan();
00453         foreach ($settings as $config=>$settingname) {
00454             $value = get_config('backup', $config);
00455             $locked = (get_config('backup', $config.'_locked') == true);
00456             if ($plan->setting_exists($settingname)) {
00457                 $setting = $plan->get_setting($settingname);
00458                 if ($setting->get_value() != $value || 1==1) {
00459                     $setting->set_value($value);
00460                     if ($locked) {
00461                         $setting->set_status(base_setting::LOCKED_BY_CONFIG);
00462                     }
00463                 }
00464             }
00465         }
00466     }
00467 }
 All Data Structures Namespaces Files Functions Variables Enumerations