Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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) task
27
 *
28
 * TODO: Finish phpdocs
29
 */
30
abstract class base_task implements checksumable, executable, loggable {
31
 
32
    /** @var string */
33
    protected $name;      // One simple name for identification purposes
34
    /** @var backup_plan|restore_plan */
35
    protected $plan;      // Plan this is part of
36
    /** @var base_setting[] */
37
    protected $settings;  // One array of base_setting elements to define this task
38
    /** @var base_step[] */
39
    protected $steps;     // One array of base_step elements
40
    /** @var bool */
41
    protected $built;     // Flag to know if one task has been built
42
    /** @var bool */
43
    protected $executed;  // Flag to know if one task has been executed
44
 
45
    /**
46
     * Constructor - instantiates one object of this class
47
     */
48
    public function __construct($name, $plan = null) {
49
        if (!is_null($plan) && !($plan instanceof base_plan)) {
50
            throw new base_task_exception('wrong_base_plan_specified');
51
        }
52
        $this->name = $name;
53
        $this->plan = $plan;
54
        $this->settings = array();
55
        $this->steps    = array();
56
        $this->built    = false;
57
        $this->executed = false;
58
        if (!is_null($plan)) { // Add the task to the plan if specified
59
            $plan->add_task($this);
60
        }
61
    }
62
 
63
    public function get_name() {
64
        return $this->name;
65
    }
66
 
67
    public function get_steps() {
68
        return $this->steps;
69
    }
70
 
71
    public function get_settings() {
72
        return $this->settings;
73
    }
74
 
75
    /**
76
     * Returns the weight of this task, an approximation of the amount of time
77
     * it will take. By default this value is 1. It can be increased for longer
78
     * tasks.
79
     *
80
     * @return int Weight
81
     */
82
    public function get_weight() {
83
        return 1;
84
    }
85
 
86
    public function get_setting($name) {
87
        // First look in task settings
88
        $result = null;
89
        foreach ($this->settings as $key => $setting) {
90
            if ($setting->get_name() == $name) {
91
                if ($result != null) {
92
                    throw new base_task_exception('multiple_settings_by_name_found', $name);
93
                } else {
94
                    $result = $setting;
95
                }
96
            }
97
        }
98
        if ($result) {
99
            return $result;
100
        } else {
101
            // Fallback to plan settings
102
            return $this->plan->get_setting($name);
103
        }
104
    }
105
 
1441 ariadna 106
    /**
107
     * Check if a setting with the given name exists.
108
     *
109
     * This method find first in the current settings and then in the plan settings.
110
     *
111
     * @param string $name Setting name
112
     * @return bool
113
     */
1 efrain 114
    public function setting_exists($name) {
1441 ariadna 115
        foreach ($this->settings as $setting) {
116
            if ($setting->get_name() == $name) {
117
                return true;
118
            }
119
        }
1 efrain 120
        return $this->plan->setting_exists($name);
121
    }
122
 
123
    public function get_setting_value($name) {
124
        return $this->get_setting($name)->get_value();
125
    }
126
 
127
    public function get_courseid() {
128
        return $this->plan->get_courseid();
129
    }
130
 
131
    public function get_basepath() {
132
        return $this->plan->get_basepath();
133
    }
134
 
135
    public function get_taskbasepath() {
136
        return $this->get_basepath();
137
    }
138
 
139
    public function get_logger() {
140
        return $this->plan->get_logger();
141
    }
142
 
143
    /**
144
     * Gets the progress reporter, which can be used to report progress within
145
     * the backup or restore process.
146
     *
147
     * @return \core\progress\base Progress reporting object
148
     */
149
    public function get_progress() {
150
        return $this->plan->get_progress();
151
    }
152
 
153
    public function log($message, $level, $a = null, $depth = null, $display = false) {
154
        backup_helper::log($message, $level, $a, $depth, $display, $this->get_logger());
155
    }
156
 
157
    public function add_step($step) {
158
        if (! $step instanceof base_step) {
159
            throw new base_task_exception('wrong_base_step_specified');
160
        }
161
        // link the step with the task
162
        $step->set_task($this);
163
        $this->steps[] = $step;
164
    }
165
 
166
    public function set_plan($plan) {
167
        if (! $plan instanceof base_plan) {
168
            throw new base_task_exception('wrong_base_plan_specified');
169
        }
170
        $this->plan = $plan;
171
        $this->define_settings(); // Settings are defined when plan & task are linked
172
    }
173
 
174
    /**
175
     * Function responsible for building the steps of any task
176
     * (must set the $built property to true)
177
     */
178
    abstract public function build();
179
 
180
    /**
181
     * Function responsible for executing the steps of any task
182
     * (setting the $executed property to  true)
183
     */
184
    public function execute() {
185
        if (!$this->built) {
186
            throw new base_task_exception('base_task_not_built', $this->name);
187
        }
188
        if ($this->executed) {
189
            throw new base_task_exception('base_task_already_executed', $this->name);
190
        }
191
 
192
        // Starts progress based on the weight of this task and number of steps.
193
        $progress = $this->get_progress();
194
        $progress->start_progress($this->get_name(), count($this->steps), $this->get_weight());
195
        $done = 0;
196
 
197
        // Execute all steps.
198
        foreach ($this->steps as $step) {
199
            $result = $step->execute();
200
            // If step returns array, it will be forwarded to plan
201
            // (TODO: shouldn't be array but proper result object)
202
            if (is_array($result) and !empty($result)) {
203
                $this->add_result($result);
204
            }
205
            $done++;
206
            $progress->progress($done);
207
        }
208
        // Mark as executed if any step has been executed
209
        if (!empty($this->steps)) {
210
            $this->executed = true;
211
        }
212
 
213
        // Finish progress for this task.
214
        $progress->end_progress();
215
    }
216
 
217
    /**
218
     * Destroy all circular references. It helps PHP 5.2 a lot!
219
     */
220
    public function destroy() {
221
        // Before reseting anything, call destroy recursively
222
        foreach ($this->steps as $step) {
223
            $step->destroy();
224
        }
225
        foreach ($this->settings as $setting) {
226
            $setting->destroy();
227
        }
228
        // Everything has been destroyed recursively, now we can reset safely
229
        $this->steps = array();
230
        $this->settings = array();
231
        $this->plan = null;
232
    }
233
 
234
    public function is_checksum_correct($checksum) {
235
        return $this->calculate_checksum() === $checksum;
236
    }
237
 
238
    public function calculate_checksum() {
239
        // Let's do it using name and settings and steps
240
        return md5($this->name . '-' .
241
                   backup_general_helper::array_checksum_recursive($this->settings) .
242
                   backup_general_helper::array_checksum_recursive($this->steps));
243
    }
244
 
245
    /**
246
     * Add the given info to the current plan's results.
247
     *
248
     * @see base_plan::add_result()
249
     * @param array $result associative array describing a result of a task/step
250
     */
251
    public function add_result($result) {
252
        if (!is_null($this->plan)) {
253
            $this->plan->add_result($result);
254
        } else {
255
            debugging('Attempting to add a result of a task not binded with a plan', DEBUG_DEVELOPER);
256
        }
257
    }
258
 
259
    /**
260
     * Return the current plan's results
261
     *
262
     * @return array|null
263
     */
264
    public function get_results() {
265
        if (!is_null($this->plan)) {
266
            return $this->plan->get_results();
267
        } else {
268
            debugging('Attempting to get results of a task not binded with a plan', DEBUG_DEVELOPER);
269
            return null;
270
        }
271
    }
272
 
273
// Protected API starts here
274
 
275
    /**
276
     * This function is invoked on activity creation in order to add all the settings
277
     * that are associated with one task. The function will, directly, inject the settings
278
     * in the task.
279
     */
280
    abstract protected function define_settings();
281
 
1441 ariadna 282
    /**
283
     * Add a setting to the task.
284
     *
285
     * @param base_setting $setting
286
     * @return void
287
     */
288
    public function add_setting($setting) {
1 efrain 289
        if (! $setting instanceof base_setting) {
290
            throw new base_setting_exception('wrong_base_setting_specified');
291
        }
292
        $this->settings[] = $setting;
293
    }
294
}
295
 
296
/*
297
 * Exception class used by all the @base_task stuff
298
 */
299
class base_task_exception extends moodle_exception {
300
 
301
    public function __construct($errorcode, $a=NULL, $debuginfo=null) {
302
        parent::__construct($errorcode, '', '', $a, $debuginfo);
303
    }
304
}