diff options
author | ArthurHoaro <arthur@hoa.ro> | 2016-01-12 19:50:48 +0100 |
---|---|---|
committer | ArthurHoaro <arthur@hoa.ro> | 2016-02-15 20:30:24 +0100 |
commit | 510377d2cb4b12d1a421e8a88bd7edb86f223451 (patch) | |
tree | 6cea29c199fc1b29ccfb78f902313019f6f9d95e /application/Updater.php | |
parent | 268a2e52659964fb7d033a1bb4d1490bf8cc49bf (diff) | |
download | Shaarli-510377d2cb4b12d1a421e8a88bd7edb86f223451.tar.gz Shaarli-510377d2cb4b12d1a421e8a88bd7edb86f223451.tar.zst Shaarli-510377d2cb4b12d1a421e8a88bd7edb86f223451.zip |
Introduce the Updater class which
* contains methods designed to be run once.
* is able to upgrade the datastore or the configuration.
* is based on methods names, stored in a text file with ';' separator (updates.txt).
* begins with existing function 'mergeDeprecatedConfigFile()' (options.php).
Diffstat (limited to 'application/Updater.php')
-rw-r--r-- | application/Updater.php | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/application/Updater.php b/application/Updater.php new file mode 100644 index 00000000..20ae0c4d --- /dev/null +++ b/application/Updater.php | |||
@@ -0,0 +1,228 @@ | |||
1 | <?php | ||
2 | |||
3 | /** | ||
4 | * Class Updater. | ||
5 | * Used to update stuff when a new Shaarli's version is reached. | ||
6 | * Update methods are ran only once, and the stored in a JSON file. | ||
7 | */ | ||
8 | class Updater | ||
9 | { | ||
10 | /** | ||
11 | * @var array Updates which are already done. | ||
12 | */ | ||
13 | protected $doneUpdates; | ||
14 | |||
15 | /** | ||
16 | * @var array Shaarli's configuration array. | ||
17 | */ | ||
18 | protected $config; | ||
19 | |||
20 | /** | ||
21 | * @var LinkDB instance. | ||
22 | */ | ||
23 | protected $linkDB; | ||
24 | |||
25 | /** | ||
26 | * @var bool True if the user is logged in, false otherwise. | ||
27 | */ | ||
28 | protected $isLoggedIn; | ||
29 | |||
30 | /** | ||
31 | * @var ReflectionMethod[] List of current class methods. | ||
32 | */ | ||
33 | protected $methods; | ||
34 | |||
35 | /** | ||
36 | * Object constructor. | ||
37 | * | ||
38 | * @param array $doneUpdates Updates which are already done. | ||
39 | * @param array $config Shaarli's configuration array. | ||
40 | * @param LinkDB $linkDB LinkDB instance. | ||
41 | * @param boolean $isLoggedIn True if the user is logged in. | ||
42 | */ | ||
43 | public function __construct($doneUpdates, $config, $linkDB, $isLoggedIn) | ||
44 | { | ||
45 | $this->doneUpdates = $doneUpdates; | ||
46 | $this->config = $config; | ||
47 | $this->linkDB = $linkDB; | ||
48 | $this->isLoggedIn = $isLoggedIn; | ||
49 | |||
50 | // Retrieve all update methods. | ||
51 | $class = new ReflectionClass($this); | ||
52 | $this->methods = $class->getMethods(); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * Run all new updates. | ||
57 | * Update methods have to start with 'updateMethod' and return true (on success). | ||
58 | * | ||
59 | * @return array An array containing ran updates. | ||
60 | * | ||
61 | * @throws UpdaterException If something went wrong. | ||
62 | */ | ||
63 | public function update() | ||
64 | { | ||
65 | $updatesRan = array(); | ||
66 | |||
67 | // If the user isn't logged in, exit without updating. | ||
68 | if ($this->isLoggedIn !== true) { | ||
69 | return $updatesRan; | ||
70 | } | ||
71 | |||
72 | if ($this->methods == null) { | ||
73 | throw new UpdaterException('Couldn\'t retrieve Updater class methods.'); | ||
74 | } | ||
75 | |||
76 | foreach ($this->methods as $method) { | ||
77 | // Not an update method or already done, pass. | ||
78 | if (! startsWith($method->getName(), 'updateMethod') | ||
79 | || in_array($method->getName(), $this->doneUpdates) | ||
80 | ) { | ||
81 | continue; | ||
82 | } | ||
83 | |||
84 | try { | ||
85 | $method->setAccessible(true); | ||
86 | $res = $method->invoke($this); | ||
87 | // Update method must return true to be considered processed. | ||
88 | if ($res === true) { | ||
89 | $updatesRan[] = $method->getName(); | ||
90 | } | ||
91 | } catch (Exception $e) { | ||
92 | throw new UpdaterException($method, $e); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | $this->doneUpdates = array_merge($this->doneUpdates, $updatesRan); | ||
97 | |||
98 | return $updatesRan; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * @return array Updates methods already processed. | ||
103 | */ | ||
104 | public function getDoneUpdates() | ||
105 | { | ||
106 | return $this->doneUpdates; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Move deprecated options.php to config.php. | ||
111 | * | ||
112 | * Milestone 0.9 (old versioning) - shaarli/Shaarli#41: | ||
113 | * options.php is not supported anymore. | ||
114 | */ | ||
115 | public function updateMethodMergeDeprecatedConfigFile() | ||
116 | { | ||
117 | $config_file = $this->config['config']['CONFIG_FILE']; | ||
118 | |||
119 | if (is_file($this->config['config']['DATADIR'].'/options.php')) { | ||
120 | include $this->config['config']['DATADIR'].'/options.php'; | ||
121 | |||
122 | // Load GLOBALS into config | ||
123 | foreach ($GLOBALS as $key => $value) { | ||
124 | $this->config[$key] = $value; | ||
125 | } | ||
126 | $this->config['config']['CONFIG_FILE'] = $config_file; | ||
127 | writeConfig($this->config, $this->isLoggedIn); | ||
128 | |||
129 | unlink($this->config['config']['DATADIR'].'/options.php'); | ||
130 | } | ||
131 | |||
132 | return true; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * Class UpdaterException. | ||
138 | */ | ||
139 | class UpdaterException extends Exception | ||
140 | { | ||
141 | /** | ||
142 | * @var string Method where the error occurred. | ||
143 | */ | ||
144 | protected $method; | ||
145 | |||
146 | /** | ||
147 | * @var Exception The parent exception. | ||
148 | */ | ||
149 | protected $previous; | ||
150 | |||
151 | /** | ||
152 | * Constructor. | ||
153 | * | ||
154 | * @param string $message Force the error message if set. | ||
155 | * @param string $method Method where the error occurred. | ||
156 | * @param Exception|bool $previous Parent exception. | ||
157 | */ | ||
158 | public function __construct($message = '', $method = '', $previous = false) | ||
159 | { | ||
160 | $this->method = $method; | ||
161 | $this->previous = $previous; | ||
162 | $this->message = $this->buildMessage($message); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Build the exception error message. | ||
167 | * | ||
168 | * @param string $message Optional given error message. | ||
169 | * | ||
170 | * @return string The built error message. | ||
171 | */ | ||
172 | private function buildMessage($message) | ||
173 | { | ||
174 | $out = ''; | ||
175 | if (! empty($message)) { | ||
176 | $out .= $message . PHP_EOL; | ||
177 | } | ||
178 | |||
179 | if (! empty($this->method)) { | ||
180 | $out .= 'An error occurred while running the update '. $this->method . PHP_EOL; | ||
181 | } | ||
182 | |||
183 | if (! empty($this->previous)) { | ||
184 | $out .= ' '. $this->previous->getMessage(); | ||
185 | } | ||
186 | |||
187 | return $out; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | |||
192 | /** | ||
193 | * Read the updates file, and return already done updates. | ||
194 | * | ||
195 | * @param string $updatesFilepath Updates file path. | ||
196 | * | ||
197 | * @return array Already done update methods. | ||
198 | */ | ||
199 | function read_updates_file($updatesFilepath) | ||
200 | { | ||
201 | if (! empty($updatesFilepath) && is_file($updatesFilepath)) { | ||
202 | $content = file_get_contents($updatesFilepath); | ||
203 | if (! empty($content)) { | ||
204 | return explode(';', $content); | ||
205 | } | ||
206 | } | ||
207 | return array(); | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * Write updates file. | ||
212 | * | ||
213 | * @param string $updatesFilepath Updates file path. | ||
214 | * @param array $updates Updates array to write. | ||
215 | * | ||
216 | * @throws Exception Couldn't write version number. | ||
217 | */ | ||
218 | function write_updates_file($updatesFilepath, $updates) | ||
219 | { | ||
220 | if (empty($updatesFilepath)) { | ||
221 | throw new Exception('Updates file path is not set, can\'t write updates.'); | ||
222 | } | ||
223 | |||
224 | $res = file_put_contents($updatesFilepath, implode(';', $updates)); | ||
225 | if ($res === false) { | ||
226 | throw new Exception('Unable to write updates in '. $updatesFilepath . '.'); | ||
227 | } | ||
228 | } | ||