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) plan
27
 *
28
 * TODO: Finish phpdocs
29
 */
30
abstract class base_plan implements checksumable, executable {
31
 
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
36
 
37
    protected $built;     // Flag to know if one plan has been built
38
 
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
    }
49
 
50
    public function get_name() {
51
        return $this->name;
52
    }
53
 
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
            // Check if there is already a setting for this name.
64
            $name = $setting->get_name();
65
            if (!isset($this->settings[$name])) {
66
                // There is no setting, so add it.
67
                $this->settings[$name] = $setting;
68
            } else if ($this->settings[$name] != $setting) {
69
                // If the setting already exists AND it is not the same setting,
70
                // then throw an error. (I.e. you're allowed to add the same
71
                // setting twice, but cannot add two different ones with same
72
                // name.)
73
                throw new base_plan_exception('multiple_settings_by_name_found', $name);
74
            }
75
        }
76
    }
77
 
78
    public function get_tasks() {
79
        return $this->tasks;
80
    }
81
 
82
    /**
83
     * Add the passed info to the plan results
84
     *
85
     * At the moment we expect an associative array structure to be merged into
86
     * the current results. In the future, some sort of base_result class may
87
     * be introduced.
88
     *
89
     * @param array $result associative array describing a result of a task/step
90
     */
91
    public function add_result($result) {
92
        if (!is_array($result)) {
93
            throw new coding_exception('Associative array is expected as a parameter of add_result()');
94
        }
95
        $this->results = array_merge($this->results, $result);
96
    }
97
 
98
    /**
99
     * Return the results collected via {@link self::add_result()} method
100
     *
101
     * @return array
102
     */
103
    public function get_results() {
104
        return $this->results;
105
    }
106
 
107
    public function get_settings() {
108
        return $this->settings;
109
    }
110
 
111
    /**
112
     * return one setting by name, useful to request root/course settings
113
     * that are, by definition, unique by name.
114
     *
115
     * @param string $name name of the setting
116
     * @return base_setting
117
     * @throws base_plan_exception if setting name is not found.
118
     */
119
    public function get_setting($name) {
120
        $result = null;
121
        if (isset($this->settings[$name])) {
122
            $result = $this->settings[$name];
123
        } else {
124
            throw new base_plan_exception('setting_by_name_not_found', $name);
125
        }
126
        return $result;
127
    }
128
 
129
    /**
130
     * For debug only. Get a simple test display of all the settings.
131
     *
132
     * @return string
133
     */
134
    public function debug_display_all_settings_values(): string {
135
        $result = '';
136
        foreach ($this->settings as $name => $setting) {
137
            $result .= $name . ': ' . $setting->get_value() . "\n";
138
        }
139
        return $result;
140
    }
141
 
142
    /**
143
     * Wrapper over @get_setting() that returns if the requested setting exists or no
144
     */
145
    public function setting_exists($name) {
146
        try {
147
            $this->get_setting($name);
148
            return true;
149
        } catch (base_plan_exception $e) {
150
            // Nothing to do
151
        }
152
        return false;
153
    }
154
 
155
 
156
    /**
157
     * Function responsible for building the tasks of any plan
158
     * with their corresponding settings
159
     * (must set the $built property to true)
160
     */
161
    abstract public function build();
162
 
163
    public function is_checksum_correct($checksum) {
164
        return $this->calculate_checksum() === $checksum;
165
    }
166
 
167
    public function calculate_checksum() {
168
        // Let's do it using name and tasks (settings are part of tasks)
169
        return md5($this->name . '-' . backup_general_helper::array_checksum_recursive($this->tasks));
170
    }
171
 
172
    /**
173
     * Function responsible for executing the tasks of any plan
174
     */
175
    public function execute() {
176
        if (!$this->built) {
177
            throw new base_plan_exception('base_plan_not_built');
178
        }
179
 
180
        // Calculate the total weight of all tasks and start progress tracking.
181
        $progress = $this->get_progress();
182
        $totalweight = 0;
183
        foreach ($this->tasks as $task) {
184
            $totalweight += $task->get_weight();
185
        }
186
        $progress->start_progress($this->get_name(), $totalweight);
187
 
188
        // Build and execute all tasks.
189
        foreach ($this->tasks as $task) {
190
            $task->build();
191
            $task->execute();
192
        }
193
 
194
        // Finish progress tracking.
195
        $progress->end_progress();
196
    }
197
 
198
    /**
199
     * Gets the progress reporter, which can be used to report progress within
200
     * the backup or restore process.
201
     *
202
     * @return \core\progress\base Progress reporting object
203
     */
204
    abstract public function get_progress();
205
 
206
    /**
207
     * Destroy all circular references. It helps PHP 5.2 a lot!
208
     */
209
    public function destroy() {
210
        // Before reseting anything, call destroy recursively
211
        foreach ($this->tasks as $task) {
212
            $task->destroy();
213
        }
214
        foreach ($this->settings as $setting) {
215
            $setting->destroy();
216
        }
217
        // Everything has been destroyed recursively, now we can reset safely
218
        $this->tasks = array();
219
        $this->settings = array();
220
    }
221
}
222
 
223
 
224
/*
225
 * Exception class used by all the @base_plan stuff
226
 */
227
class base_plan_exception extends moodle_exception {
228
 
229
    public function __construct($errorcode, $a=NULL, $debuginfo=null) {
230
        parent::__construct($errorcode, '', '', $a, $debuginfo);
231
    }
232
}