3ed176b0bbfdff682640df2733e89747e5c9975c
[moodle.git] / backup / util / plan / base_plan.class.php
1 <?php
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/>.
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  */
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 {
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
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     }
50     public function get_name() {
51         return $this->name;
52     }
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             if (!in_array($setting, $this->settings)) {
64                 $this->settings[] = $setting;
65             }
66         }
67     }
69     public function get_tasks() {
70         return $this->tasks;
71     }
73     public function add_result($result) {
74         $this->results = array_merge($this->results, $result);
75     }
77     public function get_results() {
78         return $this->results;
79     }
81     public function get_settings() {
82         return $this->settings;
83     }
85     /**
86      * return one setting by name, useful to request root/course settings
87      * that are, by definition, unique by name. Throws exception if multiple
88      * are found
89      *
90      * TODO: Change this to string indexed array for quicker lookup. Not critical
91      */
92     public function get_setting($name) {
93         $result = null;
94         foreach ($this->settings as $key => $setting) {
95             if ($setting->get_name() == $name) {
96                 if ($result != null) {
97                     throw new base_plan_exception('multiple_settings_by_name_found', $name);
98                 } else {
99                     $result = $setting;
100                 }
101             }
102         }
103         if (!$result) {
104             throw new base_plan_exception('setting_by_name_not_found', $name);
105         }
106         return $result;
107     }
109     /**
110      * Wrapper over @get_setting() that returns if the requested setting exists or no
111      */
112     public function setting_exists($name) {
113         try {
114             $this->get_setting($name);
115             return true;
116         } catch (base_plan_exception $e) {
117             // Nothing to do
118         }
119         return false;
120     }
123     /**
124      * Function responsible for building the tasks of any plan
125      * with their corresponding settings
126      * (must set the $built property to true)
127      */
128     public abstract function build();
130     public function is_checksum_correct($checksum) {
131         return $this->calculate_checksum() === $checksum;
132     }
134     public function calculate_checksum() {
135         // Let's do it using name and tasks (settings are part of tasks)
136         return md5($this->name . '-' . backup_general_helper::array_checksum_recursive($this->tasks));
137     }
139     /**
140      * Function responsible for executing the tasks of any plan
141      */
142     public function execute() {
143         if (!$this->built) {
144             throw new base_plan_exception('base_plan_not_built');
145         }
146         foreach ($this->tasks as $task) {
147             $task->build();
148             $task->execute();
149         }
150     }
152     /**
153      * Destroy all circular references. It helps PHP 5.2 a lot!
154      */
155     public function destroy() {
156         // Before reseting anything, call destroy recursively
157         foreach ($this->tasks as $task) {
158             $task->destroy();
159         }
160         foreach ($this->settings as $setting) {
161             $setting->destroy();
162         }
163         // Everything has been destroyed recursively, now we can reset safely
164         $this->tasks = array();
165         $this->settings = array();
166     }
170 /*
171  * Exception class used by all the @base_plan stuff
172  */
173 class base_plan_exception extends moodle_exception {
175     public function __construct($errorcode, $a=NULL, $debuginfo=null) {
176         parent::__construct($errorcode, '', '', $a, $debuginfo);
177     }