|
Moodle
2.2.1
http://www.collinsharper.com
|
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 }