3 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
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
26 * Abstract class defining the basis for one execution (backup/restore) plan
28 * TODO: Finish phpdocs
30 abstract class base_plan
implements checksumable
, executable
{
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
37 protected $built; // Flag to know if one plan has been built
40 * Constructor - instantiates one object of this class
42 public function __construct($name) {
44 $this->settings
= array();
45 $this->tasks
= array();
46 $this->results
= array();
50 public function get_name() {
54 public function add_task($task) {
55 if (! $task instanceof base_task
) {
56 throw new base_plan_exception('wrong_base_task_specified');
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
73 throw new base_plan_exception('multiple_settings_by_name_found', $name);
78 public function get_tasks() {
83 * Add the passed info to the plan results
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
89 * @param array $result associative array describing a result of a task/step
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()');
95 $this->results
= array_merge($this->results
, $result);
99 * Return the results collected via {@link self::add_result()} method
103 public function get_results() {
104 return $this->results
;
107 public function get_settings() {
108 return $this->settings
;
112 * return one setting by name, useful to request root/course settings
113 * that are, by definition, unique by name.
115 * @param string $name name of the setting
116 * @return base_setting
117 * @throws base_plan_exception if setting name is not found.
119 public function get_setting($name) {
121 if (isset($this->settings
[$name])) {
122 $result = $this->settings
[$name];
124 throw new base_plan_exception('setting_by_name_not_found', $name);
130 * Wrapper over @get_setting() that returns if the requested setting exists or no
132 public function setting_exists($name) {
134 $this->get_setting($name);
136 } catch (base_plan_exception
$e) {
144 * Function responsible for building the tasks of any plan
145 * with their corresponding settings
146 * (must set the $built property to true)
148 public abstract function build();
150 public function is_checksum_correct($checksum) {
151 return $this->calculate_checksum() === $checksum;
154 public function calculate_checksum() {
155 // Let's do it using name and tasks (settings are part of tasks)
156 return md5($this->name
. '-' . backup_general_helper
::array_checksum_recursive($this->tasks
));
160 * Function responsible for executing the tasks of any plan
162 public function execute() {
164 throw new base_plan_exception('base_plan_not_built');
167 // Calculate the total weight of all tasks and start progress tracking.
168 $progress = $this->get_progress();
170 foreach ($this->tasks
as $task) {
171 $totalweight +
= $task->get_weight();
173 $progress->start_progress($this->get_name(), $totalweight);
175 // Build and execute all tasks.
176 foreach ($this->tasks
as $task) {
181 // Finish progress tracking.
182 $progress->end_progress();
186 * Gets the progress reporter, which can be used to report progress within
187 * the backup or restore process.
189 * @return \core\progress\base Progress reporting object
191 public abstract function get_progress();
194 * Destroy all circular references. It helps PHP 5.2 a lot!
196 public function destroy() {
197 // Before reseting anything, call destroy recursively
198 foreach ($this->tasks
as $task) {
201 foreach ($this->settings
as $setting) {
204 // Everything has been destroyed recursively, now we can reset safely
205 $this->tasks
= array();
206 $this->settings
= array();
212 * Exception class used by all the @base_plan stuff
214 class base_plan_exception
extends moodle_exception
{
216 public function __construct($errorcode, $a=NULL, $debuginfo=null) {
217 parent
::__construct($errorcode, '', '', $a, $debuginfo);