Proyectos de Subversion Moodle

Rev

| 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
 
106
    public function setting_exists($name) {
107
        return $this->plan->setting_exists($name);
108
    }
109
 
110
    public function get_setting_value($name) {
111
        return $this->get_setting($name)->get_value();
112
    }
113
 
114
    public function get_courseid() {
115
        return $this->plan->get_courseid();
116
    }
117
 
118
    public function get_basepath() {
119
        return $this->plan->get_basepath();
120
    }
121
 
122
    public function get_taskbasepath() {
123
        return $this->get_basepath();
124
    }
125
 
126
    public function get_logger() {
127
        return $this->plan->get_logger();
128
    }
129
 
130
    /**
131
     * Gets the progress reporter, which can be used to report progress within
132
     * the backup or restore process.
133
     *
134
     * @return \core\progress\base Progress reporting object
135
     */
136
    public function get_progress() {
137
        return $this->plan->get_progress();
138
    }
139
 
140
    public function log($message, $level, $a = null, $depth = null, $display = false) {
141
        backup_helper::log($message, $level, $a, $depth, $display, $this->get_logger());
142
    }
143
 
144
    public function add_step($step) {
145
        if (! $step instanceof base_step) {
146
            throw new base_task_exception('wrong_base_step_specified');
147
        }
148
        // link the step with the task
149
        $step->set_task($this);
150
        $this->steps[] = $step;
151
    }
152
 
153
    public function set_plan($plan) {
154
        if (! $plan instanceof base_plan) {
155
            throw new base_task_exception('wrong_base_plan_specified');
156
        }
157
        $this->plan = $plan;
158
        $this->define_settings(); // Settings are defined when plan & task are linked
159
    }
160
 
161
    /**
162
     * Function responsible for building the steps of any task
163
     * (must set the $built property to true)
164
     */
165
    abstract public function build();
166
 
167
    /**
168
     * Function responsible for executing the steps of any task
169
     * (setting the $executed property to  true)
170
     */
171
    public function execute() {
172
        if (!$this->built) {
173
            throw new base_task_exception('base_task_not_built', $this->name);
174
        }
175
        if ($this->executed) {
176
            throw new base_task_exception('base_task_already_executed', $this->name);
177
        }
178
 
179
        // Starts progress based on the weight of this task and number of steps.
180
        $progress = $this->get_progress();
181
        $progress->start_progress($this->get_name(), count($this->steps), $this->get_weight());
182
        $done = 0;
183
 
184
        // Execute all steps.
185
        foreach ($this->steps as $step) {
186
            $result = $step->execute();
187
            // If step returns array, it will be forwarded to plan
188
            // (TODO: shouldn't be array but proper result object)
189
            if (is_array($result) and !empty($result)) {
190
                $this->add_result($result);
191
            }
192
            $done++;
193
            $progress->progress($done);
194
        }
195
        // Mark as executed if any step has been executed
196
        if (!empty($this->steps)) {
197
            $this->executed = true;
198
        }
199
 
200
        // Finish progress for this task.
201
        $progress->end_progress();
202
    }
203
 
204
    /**
205
     * Destroy all circular references. It helps PHP 5.2 a lot!
206
     */
207
    public function destroy() {
208
        // Before reseting anything, call destroy recursively
209
        foreach ($this->steps as $step) {
210
            $step->destroy();
211
        }
212
        foreach ($this->settings as $setting) {
213
            $setting->destroy();
214
        }
215
        // Everything has been destroyed recursively, now we can reset safely
216
        $this->steps = array();
217
        $this->settings = array();
218
        $this->plan = null;
219
    }
220
 
221
    public function is_checksum_correct($checksum) {
222
        return $this->calculate_checksum() === $checksum;
223
    }
224
 
225
    public function calculate_checksum() {
226
        // Let's do it using name and settings and steps
227
        return md5($this->name . '-' .
228
                   backup_general_helper::array_checksum_recursive($this->settings) .
229
                   backup_general_helper::array_checksum_recursive($this->steps));
230
    }
231
 
232
    /**
233
     * Add the given info to the current plan's results.
234
     *
235
     * @see base_plan::add_result()
236
     * @param array $result associative array describing a result of a task/step
237
     */
238
    public function add_result($result) {
239
        if (!is_null($this->plan)) {
240
            $this->plan->add_result($result);
241
        } else {
242
            debugging('Attempting to add a result of a task not binded with a plan', DEBUG_DEVELOPER);
243
        }
244
    }
245
 
246
    /**
247
     * Return the current plan's results
248
     *
249
     * @return array|null
250
     */
251
    public function get_results() {
252
        if (!is_null($this->plan)) {
253
            return $this->plan->get_results();
254
        } else {
255
            debugging('Attempting to get results of a task not binded with a plan', DEBUG_DEVELOPER);
256
            return null;
257
        }
258
    }
259
 
260
// Protected API starts here
261
 
262
    /**
263
     * This function is invoked on activity creation in order to add all the settings
264
     * that are associated with one task. The function will, directly, inject the settings
265
     * in the task.
266
     */
267
    abstract protected function define_settings();
268
 
269
    protected function add_setting($setting) {
270
        if (! $setting instanceof base_setting) {
271
            throw new base_setting_exception('wrong_base_setting_specified');
272
        }
273
        $this->settings[] = $setting;
274
    }
275
}
276
 
277
/*
278
 * Exception class used by all the @base_task stuff
279
 */
280
class base_task_exception extends moodle_exception {
281
 
282
    public function __construct($errorcode, $a=NULL, $debuginfo=null) {
283
        parent::__construct($errorcode, '', '', $a, $debuginfo);
284
    }
285
}