341e71d4fd10b40528af2f03f8de5dded3942c37
[moodle.git] / backup / util / plan / base_task.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) task
27  *
28  * TODO: Finish phpdocs
29  */
30 abstract class base_task implements checksumable, executable, loggable {
32     protected $name;      // One simple name for identification purposes
33     protected $plan;      // Plan this is part of
34     protected $settings;  // One array of base_setting elements to define this task
35     protected $steps;     // One array of base_task elements
37     protected $built;     // Flag to know if one task has been built
38     protected $executed;  // Flag to know if one task has been executed
40     /**
41      * Constructor - instantiates one object of this class
42      */
43     public function __construct($name, $plan = null) {
44         if (!is_null($plan) && !($plan instanceof base_plan)) {
45             throw new base_task_exception('wrong_base_plan_specified');
46         }
47         $this->name = $name;
48         $this->plan = $plan;
49         $this->settings = array();
50         $this->steps    = array();
51         $this->built    = false;
52         $this->executed = false;
53         if (!is_null($plan)) { // Add the task to the plan if specified
54             $plan->add_task($this);
55         }
56     }
58     public function get_name() {
59         return $this->name;
60     }
62     public function get_steps() {
63         return $this->steps;
64     }
66     public function get_settings() {
67         return $this->settings;
68     }
70     public function get_setting($name) {
71         // First look in task settings
72         $result = null;
73         foreach ($this->settings as $key => $setting) {
74             if ($setting->get_name() == $name) {
75                 if ($result != null) {
76                     throw new base_task_exception('multiple_settings_by_name_found', $name);
77                 } else {
78                     $result = $setting;
79                 }
80             }
81         }
82         if ($result) {
83             return $result;
84         } else {
85             // Fallback to plan settings
86             return $this->plan->get_setting($name);
87         }
88     }
90     public function get_setting_value($name) {
91         return $this->get_setting($name)->get_value();
92     }
94     public function get_courseid() {
95         return $this->plan->get_courseid();
96     }
98     public function get_basepath() {
99         return $this->plan->get_basepath();
100     }
102     public function get_taskbasepath() {
103         return $this->get_basepath();
104     }
106     public function get_logger() {
107         return $this->plan->get_logger();
108     }
110     public function log($message, $level, $a = null, $depth = null, $display = false) {
111         backup_helper::log($message, $level, $a, $depth, $display, $this->get_logger());
112     }
114     public function add_step($step) {
115         if (! $step instanceof base_step) {
116             throw new base_task_exception('wrong_base_step_specified');
117         }
118         // link the step with the task
119         $step->set_task($this);
120         $this->steps[] = $step;
121     }
123     public function set_plan($plan) {
124         if (! $plan instanceof base_plan) {
125             throw new base_task_exception('wrong_base_plan_specified');
126         }
127         $this->plan = $plan;
128         $this->define_settings(); // Settings are defined when plan & task are linked
129     }
131     /**
132      * Function responsible for building the steps of any task
133      * (must set the $built property to true)
134      */
135     public abstract function build();
137     /**
138      * Function responsible for executing the steps of any task
139      * (setting the $executed property to  true)
140      */
141     public function execute() {
142         if (!$this->built) {
143             throw new base_task_exception('base_task_not_built', $this->name);
144         }
145         if ($this->executed) {
146             throw new base_task_exception('base_task_already_executed', $this->name);
147         }
148         foreach ($this->steps as $step) {
149             $result = $step->execute();
150             // If step returns array, it will be forwarded to plan
151             // (TODO: shouldn't be array but proper result object)
152             if (is_array($result) and !empty($result)) {
153                 $this->plan->add_result($result);
154             }
155         }
156         // Mark as executed if any step has been executed
157         if (!empty($this->steps)) {
158             $this->executed = true;
159         }
160     }
162     public function is_checksum_correct($checksum) {
163         return $this->calculate_checksum() === $checksum;
164     }
166     public function calculate_checksum() {
167         // Let's do it using name and settings and steps
168         return md5($this->name . '-' .
169                    backup_general_helper::array_checksum_recursive($this->settings) .
170                    backup_general_helper::array_checksum_recursive($this->steps));
171     }
173 // Protected API starts here
175     /**
176      * This function is invoked on activity creation in order to add all the settings
177      * that are associated with one task. The function will, directly, inject the settings
178      * in the task.
179      */
180     protected abstract function define_settings();
182     protected function add_setting($setting) {
183         if (! $setting instanceof base_setting) {
184             throw new base_setting_exception('wrong_base_setting_specified');
185         }
186         $this->settings[] = $setting;
187     }
190 /*
191  * Exception class used by all the @base_task stuff
192  */
193 class base_task_exception extends moodle_exception {
195     public function __construct($errorcode, $a=NULL, $debuginfo=null) {
196         parent::__construct($errorcode, '', '', $a, $debuginfo);
197     }