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