Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/backup/controller/backup_controller.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 
00043 class backup_controller extends backup implements loggable {
00044 
00045     protected $backupid; // Unique identificator for this backup
00046 
00047     protected $type;   // Type of backup (activity, section, course)
00048     protected $id;     // Course/section/course_module id to backup
00049     protected $courseid; // courseid where the id belongs to
00050     protected $format; // Format of backup (moodle, imscc)
00051     protected $interactive; // yes/no
00052     protected $mode;   // Purpose of the backup (default settings)
00053     protected $userid; // user id executing the backup
00054     protected $operation; // Type of operation (backup/restore)
00055 
00056     protected $status; // Current status of the controller (created, planned, configured...)
00057 
00058     protected $plan;   // Backup execution plan
00059 
00060     protected $execution;     // inmediate/delayed
00061     protected $executiontime; // epoch time when we want the backup to be executed (requires cron to run)
00062 
00063     protected $destination; // Destination chain object (fs_moodle, fs_os, db, email...)
00064     protected $logger;      // Logging chain object (moodle, inline, fs, db, syslog)
00065 
00066     protected $checksum; // Cache @checksumable results for lighter @is_checksum_correct() uses
00067 
00078     public function __construct($type, $id, $format, $interactive, $mode, $userid){
00079         $this->type = $type;
00080         $this->id   = $id;
00081         $this->courseid = backup_controller_dbops::get_courseid_from_type_id($this->type, $this->id);
00082         $this->format = $format;
00083         $this->interactive = $interactive;
00084         $this->mode = $mode;
00085         $this->userid = $userid;
00086 
00087         // Apply some defaults
00088         $this->execution = backup::EXECUTION_INMEDIATE;
00089         $this->operation = backup::OPERATION_BACKUP;
00090         $this->executiontime = 0;
00091         $this->checksum = '';
00092 
00093         // Apply current backup version and release if necessary
00094         backup_controller_dbops::apply_version_and_release();
00095 
00096         // Check format and type are correct
00097         backup_check::check_format_and_type($this->format, $this->type);
00098 
00099         // Check id is correct
00100         backup_check::check_id($this->type, $this->id);
00101 
00102         // Check user is correct
00103         backup_check::check_user($this->userid);
00104 
00105         // Calculate unique $backupid
00106         $this->calculate_backupid();
00107 
00108         // Default logger chain (based on interactive/execution)
00109         $this->logger = backup_factory::get_logger_chain($this->interactive, $this->execution, $this->backupid);
00110 
00111         // Instantiate the output_controller singleton and active it if interactive and inmediate
00112         $oc = output_controller::get_instance();
00113         if ($this->interactive == backup::INTERACTIVE_YES && $this->execution == backup::EXECUTION_INMEDIATE) {
00114             $oc->set_active(true);
00115         }
00116 
00117         $this->log('instantiating backup controller', backup::LOG_INFO, $this->backupid);
00118 
00119         // Default destination chain (based on type/mode/execution)
00120         $this->destination = backup_factory::get_destination_chain($this->type, $this->id, $this->mode, $this->execution);
00121 
00122         // Set initial status
00123         $this->set_status(backup::STATUS_CREATED);
00124 
00125         // Load plan (based on type/format)
00126         $this->load_plan();
00127 
00128         // Apply all default settings (based on type/format/mode)
00129         $this->apply_defaults();
00130 
00131         // Perform all initial security checks and apply (2nd param) them to settings automatically
00132         backup_check::check_security($this, true);
00133 
00134         // Set status based on interactivity
00135         if ($this->interactive == backup::INTERACTIVE_YES) {
00136             $this->set_status(backup::STATUS_SETTING_UI);
00137         } else {
00138             $this->set_status(backup::STATUS_AWAITING);
00139         }
00140     }
00141 
00154     public function destroy() {
00155         // Only need to destroy circulars under the plan. Delegate to it.
00156         $this->plan->destroy();
00157     }
00158 
00159     public function finish_ui() {
00160         if ($this->status != backup::STATUS_SETTING_UI) {
00161             throw new backup_controller_exception('cannot_finish_ui_if_not_setting_ui');
00162         }
00163         $this->set_status(backup::STATUS_AWAITING);
00164     }
00165 
00166     public function process_ui_event() {
00167 
00168         // Perform security checks throwing exceptions (2nd param) if something is wrong
00169         backup_check::check_security($this, false);
00170     }
00171 
00172     public function set_status($status) {
00173         $this->log('setting controller status to', backup::LOG_DEBUG, $status);
00174         // TODO: Check it's a correct status
00175         $this->status = $status;
00176         // Ensure that, once set to backup::STATUS_AWAITING, controller is stored in DB
00177         // Note: never save_controller() after STATUS_EXECUTING or the whole controller,
00178         // containing all the steps will be sent to DB. 100% (monster) useless.
00179         if ($status == backup::STATUS_AWAITING) {
00180             $this->save_controller();
00181             $tbc = self::load_controller($this->backupid);
00182             $this->logger = $tbc->logger; // wakeup loggers
00183             $tbc->destroy(); // Clean temp controller structures
00184         }
00185     }
00186 
00187     public function set_execution($execution, $executiontime = 0) {
00188         $this->log('setting controller execution', backup::LOG_DEBUG);
00189         // TODO: Check valid execution mode
00190         // TODO: Check time in future
00191         // TODO: Check time = 0 if inmediate
00192         $this->execution = $execution;
00193         $this->executiontime = $executiontime;
00194 
00195         // Default destination chain (based on type/mode/execution)
00196         $this->destination = backup_factory::get_destination_chain($this->type, $this->id, $this->mode, $this->execution);
00197 
00198         // Default logger chain (based on interactive/execution)
00199         $this->logger = backup_factory::get_logger_chain($this->interactive, $this->execution, $this->backupid);
00200     }
00201 
00202 // checksumable interface methods
00203 
00204     public function calculate_checksum() {
00205         // Reset current checksum to take it out from calculations!
00206         $this->checksum = '';
00207         // Init checksum
00208         $tempchecksum = md5('backupid-'   . $this->backupid .
00209                             'type-'       . $this->type .
00210                             'id-'         . $this->id .
00211                             'format-'     . $this->format .
00212                             'interactive-'. $this->interactive .
00213                             'mode-'       . $this->mode .
00214                             'userid-'     . $this->userid .
00215                             'operation-'  . $this->operation .
00216                             'status-'     . $this->status .
00217                             'execution-'  . $this->execution .
00218                             'plan-'       . backup_general_helper::array_checksum_recursive(array($this->plan)) .
00219                             'destination-'. backup_general_helper::array_checksum_recursive(array($this->destination)) .
00220                             'logger-'     . backup_general_helper::array_checksum_recursive(array($this->logger)));
00221         $this->log('calculating controller checksum', backup::LOG_DEBUG, $tempchecksum);
00222         return $tempchecksum;
00223     }
00224 
00225     public function is_checksum_correct($checksum) {
00226         return $this->checksum === $checksum;
00227     }
00228 
00229     public function get_backupid() {
00230         return $this->backupid;
00231     }
00232 
00233     public function get_type() {
00234         return $this->type;
00235     }
00236 
00237     public function get_operation() {
00238         return $this->operation;
00239     }
00240 
00241     public function get_id() {
00242         return $this->id;
00243     }
00244 
00245     public function get_courseid() {
00246         return $this->courseid;
00247     }
00248 
00249     public function get_format() {
00250         return $this->format;
00251     }
00252 
00253     public function get_interactive() {
00254         return $this->interactive;
00255     }
00256 
00257     public function get_mode() {
00258         return $this->mode;
00259     }
00260 
00261     public function get_userid() {
00262         return $this->userid;
00263     }
00264 
00265     public function get_status() {
00266         return $this->status;
00267     }
00268 
00269     public function get_execution() {
00270         return $this->execution;
00271     }
00272 
00273     public function get_executiontime() {
00274         return $this->executiontime;
00275     }
00276 
00280     public function get_plan() {
00281         return $this->plan;
00282     }
00283 
00284     public function get_logger() {
00285         return $this->logger;
00286     }
00287 
00292     public function execute_plan() {
00293         // Basic/initial prevention against time/memory limits
00294         set_time_limit(1 * 60 * 60); // 1 hour for 1 course initially granted
00295         raise_memory_limit(MEMORY_EXTRA);
00296         // If this is not a course backup, inform the plan we are not
00297         // including all the activities for sure. This will affect any
00298         // task/step executed conditionally to stop including information
00299         // for section and activity backup. MDL-28180.
00300         if ($this->get_type() !== backup::TYPE_1COURSE) {
00301             $this->log('notifying plan about excluded activities by type', backup::LOG_DEBUG);
00302             $this->plan->set_excluding_activities();
00303         }
00304         return $this->plan->execute();
00305     }
00306 
00307     public function get_results() {
00308         return $this->plan->get_results();
00309     }
00310 
00311     public function log($message, $level, $a = null, $depth = null, $display = false) {
00312         backup_helper::log($message, $level, $a, $depth, $display, $this->logger);
00313     }
00314 
00315     public function save_controller() {
00316         // Going to save controller to persistent storage, calculate checksum for later checks and save it
00317         // TODO: flag the controller as NA. Any operation on it should be forbidden util loaded back
00318         $this->log('saving controller to db', backup::LOG_DEBUG);
00319         $this->checksum = $this->calculate_checksum();
00320         backup_controller_dbops::save_controller($this, $this->checksum);
00321     }
00322 
00323     public static function load_controller($backupid) {
00324         // Load controller from persistent storage
00325         // TODO: flag the controller as available. Operations on it can continue
00326         $controller = backup_controller_dbops::load_controller($backupid);
00327         $controller->log('loading controller from db', backup::LOG_DEBUG);
00328         return $controller;
00329     }
00330 
00331 // Protected API starts here
00332 
00333     protected function calculate_backupid() {
00334         // Current epoch time + type + id + format + interactive + mode + userid + operation
00335         // should be unique enough. Add one random part at the end
00336         $this->backupid = md5(time() . '-' . $this->type . '-' . $this->id . '-' . $this->format . '-' .
00337                               $this->interactive . '-' . $this->mode . '-' . $this->userid . '-' .
00338                               $this->operation . '-' . random_string(20));
00339     }
00340 
00341     protected function load_plan() {
00342         $this->log('loading controller plan', backup::LOG_DEBUG);
00343         $this->plan = new backup_plan($this);
00344         $this->plan->build(); // Build plan for this controller
00345         $this->set_status(backup::STATUS_PLANNED);
00346     }
00347 
00348     protected function apply_defaults() {
00349         $this->log('applying plan defaults', backup::LOG_DEBUG);
00350         backup_controller_dbops::apply_config_defaults($this);
00351         $this->set_status(backup::STATUS_CONFIGURED);
00352     }
00353 }
00354 
00355 /*
00356  * Exception class used by all the @backup_controller stuff
00357  */
00358 class backup_controller_exception extends backup_exception {
00359 
00360     public function __construct($errorcode, $a=NULL, $debuginfo=null) {
00361         parent::__construct($errorcode, $a, $debuginfo);
00362     }
00363 }
 All Data Structures Namespaces Files Functions Variables Enumerations