1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * @package moodlecore 20 * @subpackage backup-plan 21 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 /** 26 * Abstract class defining the basis for one execution (backup/restore) plan 27 * 28 * TODO: Finish phpdocs 29 */ 30 abstract class base_plan implements checksumable, executable { 31 32 protected $name; // One simple name for identification purposes 33 protected $settings; // One array of (accumulated from tasks) base_setting elements 34 protected $tasks; // One array of base_task elements 35 protected $results; // One array of results received from tasks 36 37 protected $built; // Flag to know if one plan has been built 38 39 /** 40 * Constructor - instantiates one object of this class 41 */ 42 public function __construct($name) { 43 $this->name = $name; 44 $this->settings = array(); 45 $this->tasks = array(); 46 $this->results = array(); 47 $this->built = false; 48 } 49 50 public function get_name() { 51 return $this->name; 52 } 53 54 public function add_task($task) { 55 if (! $task instanceof base_task) { 56 throw new base_plan_exception('wrong_base_task_specified'); 57 } 58 $this->tasks[] = $task; 59 // link the task with the plan 60 $task->set_plan($this); 61 // Append task settings to plan array, if not present, for comodity 62 foreach ($task->get_settings() as $key => $setting) { 63 // Check if there is already a setting for this name. 64 $name = $setting->get_name(); 65 if (!isset($this->settings[$name])) { 66 // There is no setting, so add it. 67 $this->settings[$name] = $setting; 68 } else if ($this->settings[$name] != $setting) { 69 // If the setting already exists AND it is not the same setting, 70 // then throw an error. (I.e. you're allowed to add the same 71 // setting twice, but cannot add two different ones with same 72 // name.) 73 throw new base_plan_exception('multiple_settings_by_name_found', $name); 74 } 75 } 76 } 77 78 public function get_tasks() { 79 return $this->tasks; 80 } 81 82 /** 83 * Add the passed info to the plan results 84 * 85 * At the moment we expect an associative array structure to be merged into 86 * the current results. In the future, some sort of base_result class may 87 * be introduced. 88 * 89 * @param array $result associative array describing a result of a task/step 90 */ 91 public function add_result($result) { 92 if (!is_array($result)) { 93 throw new coding_exception('Associative array is expected as a parameter of add_result()'); 94 } 95 $this->results = array_merge($this->results, $result); 96 } 97 98 /** 99 * Return the results collected via {@link self::add_result()} method 100 * 101 * @return array 102 */ 103 public function get_results() { 104 return $this->results; 105 } 106 107 public function get_settings() { 108 return $this->settings; 109 } 110 111 /** 112 * return one setting by name, useful to request root/course settings 113 * that are, by definition, unique by name. 114 * 115 * @param string $name name of the setting 116 * @return base_setting 117 * @throws base_plan_exception if setting name is not found. 118 */ 119 public function get_setting($name) { 120 $result = null; 121 if (isset($this->settings[$name])) { 122 $result = $this->settings[$name]; 123 } else { 124 throw new base_plan_exception('setting_by_name_not_found', $name); 125 } 126 return $result; 127 } 128 129 /** 130 * For debug only. Get a simple test display of all the settings. 131 * 132 * @return string 133 */ 134 public function debug_display_all_settings_values(): string { 135 $result = ''; 136 foreach ($this->settings as $name => $setting) { 137 $result .= $name . ': ' . $setting->get_value() . "\n"; 138 } 139 return $result; 140 } 141 142 /** 143 * Wrapper over @get_setting() that returns if the requested setting exists or no 144 */ 145 public function setting_exists($name) { 146 try { 147 $this->get_setting($name); 148 return true; 149 } catch (base_plan_exception $e) { 150 // Nothing to do 151 } 152 return false; 153 } 154 155 156 /** 157 * Function responsible for building the tasks of any plan 158 * with their corresponding settings 159 * (must set the $built property to true) 160 */ 161 public abstract function build(); 162 163 public function is_checksum_correct($checksum) { 164 return $this->calculate_checksum() === $checksum; 165 } 166 167 public function calculate_checksum() { 168 // Let's do it using name and tasks (settings are part of tasks) 169 return md5($this->name . '-' . backup_general_helper::array_checksum_recursive($this->tasks)); 170 } 171 172 /** 173 * Function responsible for executing the tasks of any plan 174 */ 175 public function execute() { 176 if (!$this->built) { 177 throw new base_plan_exception('base_plan_not_built'); 178 } 179 180 // Calculate the total weight of all tasks and start progress tracking. 181 $progress = $this->get_progress(); 182 $totalweight = 0; 183 foreach ($this->tasks as $task) { 184 $totalweight += $task->get_weight(); 185 } 186 $progress->start_progress($this->get_name(), $totalweight); 187 188 // Build and execute all tasks. 189 foreach ($this->tasks as $task) { 190 $task->build(); 191 $task->execute(); 192 } 193 194 // Finish progress tracking. 195 $progress->end_progress(); 196 } 197 198 /** 199 * Gets the progress reporter, which can be used to report progress within 200 * the backup or restore process. 201 * 202 * @return \core\progress\base Progress reporting object 203 */ 204 public abstract function get_progress(); 205 206 /** 207 * Destroy all circular references. It helps PHP 5.2 a lot! 208 */ 209 public function destroy() { 210 // Before reseting anything, call destroy recursively 211 foreach ($this->tasks as $task) { 212 $task->destroy(); 213 } 214 foreach ($this->settings as $setting) { 215 $setting->destroy(); 216 } 217 // Everything has been destroyed recursively, now we can reset safely 218 $this->tasks = array(); 219 $this->settings = array(); 220 } 221 } 222 223 224 /* 225 * Exception class used by all the @base_plan stuff 226 */ 227 class base_plan_exception extends moodle_exception { 228 229 public function __construct($errorcode, $a=NULL, $debuginfo=null) { 230 parent::__construct($errorcode, '', '', $a, $debuginfo); 231 } 232 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body