Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 80 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
extension_manager | |
0.00% |
0 / 80 |
|
0.00% |
0 / 11 |
1640 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
pre_install | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
post_install | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
pre_update | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
30 | |||
post_update | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
remove | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
pre_remove | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
56 | |||
start_managing | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
90 | |||
check_requirements | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
set_enable_on_install | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
set_purge_on_remove | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | namespace phpbb\composer; |
15 | |
16 | use Composer\IO\IOInterface; |
17 | use phpbb\cache\driver\driver_interface; |
18 | use phpbb\composer\exception\managed_with_clean_error_exception; |
19 | use phpbb\composer\exception\managed_with_enable_error_exception; |
20 | use phpbb\composer\exception\runtime_exception; |
21 | use phpbb\config\config; |
22 | use phpbb\extension\manager as ext_manager; |
23 | use phpbb\filesystem\exception\filesystem_exception; |
24 | use phpbb\filesystem\filesystem; |
25 | |
26 | /** |
27 | * Class to safely manage extensions through composer. |
28 | */ |
29 | class extension_manager extends manager |
30 | { |
31 | /** |
32 | * @var ext_manager |
33 | */ |
34 | protected $extension_manager; |
35 | |
36 | /** |
37 | * @var filesystem |
38 | */ |
39 | protected $filesystem; |
40 | |
41 | /** |
42 | * @var string |
43 | */ |
44 | protected $root_path; |
45 | |
46 | /** |
47 | * @var array |
48 | */ |
49 | private $enabled_extensions; |
50 | |
51 | /** |
52 | * @var bool Enables extensions when installing them? |
53 | */ |
54 | private $enable_on_install = false; |
55 | |
56 | /** |
57 | * @var bool Purges extensions data when removing them? |
58 | */ |
59 | private $purge_on_remove = true; |
60 | |
61 | /** |
62 | * @param installer $installer Installer object |
63 | * @param driver_interface $cache Cache object |
64 | * @param ext_manager $extension_manager phpBB extension manager |
65 | * @param filesystem $filesystem Filesystem object |
66 | * @param string $package_type Composer type of managed packages |
67 | * @param string $exception_prefix Exception prefix to use |
68 | * @param string $root_path phpBB root path |
69 | * @param config|null $config Config object |
70 | */ |
71 | public function __construct(installer $installer, driver_interface $cache, ext_manager $extension_manager, filesystem $filesystem, $package_type, $exception_prefix, $root_path, config $config = null) |
72 | { |
73 | $this->extension_manager = $extension_manager; |
74 | $this->filesystem = $filesystem; |
75 | $this->root_path = $root_path; |
76 | |
77 | if ($config) |
78 | { |
79 | $this->enable_on_install = (bool) $config['exts_composer_enable_on_install']; |
80 | $this->purge_on_remove = (bool) $config['exts_composer_purge_on_remove']; |
81 | } |
82 | |
83 | parent::__construct($installer, $cache, $package_type, $exception_prefix); |
84 | } |
85 | |
86 | /** |
87 | * {@inheritdoc} |
88 | */ |
89 | public function pre_install(array $packages, IOInterface $io = null) |
90 | { |
91 | $installed_manually = array_intersect(array_keys($this->extension_manager->all_available()), array_keys($packages)); |
92 | if (count($installed_manually) !== 0) |
93 | { |
94 | throw new runtime_exception($this->exception_prefix, 'ALREADY_INSTALLED_MANUALLY', [implode('|', array_keys($installed_manually))]); |
95 | } |
96 | } |
97 | |
98 | /** |
99 | * {@inheritdoc} |
100 | */ |
101 | public function post_install(array $packages, IOInterface $io = null) |
102 | { |
103 | if ($this->enable_on_install) |
104 | { |
105 | /** @psalm-suppress InvalidArgument */ |
106 | $io->writeError([['ENABLING_EXTENSIONS', [], 1]]); |
107 | foreach ($packages as $package => $version) |
108 | { |
109 | try |
110 | { |
111 | $this->extension_manager->enable($package); |
112 | } |
113 | catch (\phpbb\exception\runtime_exception $e) |
114 | { |
115 | /** @psalm-suppress InvalidArgument */ |
116 | $io->writeError([[$e->getMessage(), $e->get_parameters(), 4]]); |
117 | } |
118 | catch (\Exception $e) |
119 | { |
120 | /** @psalm-suppress InvalidArgument */ |
121 | $io->writeError([[$e->getMessage(), [], 4]]); |
122 | } |
123 | } |
124 | } |
125 | } |
126 | |
127 | /** |
128 | * {@inheritdoc} |
129 | */ |
130 | protected function pre_update(array $packages, IOInterface $io = null) |
131 | { |
132 | /** @psalm-suppress InvalidArgument */ |
133 | $io->writeError([['DISABLING_EXTENSIONS', [], 1]]); |
134 | $this->enabled_extensions = []; |
135 | foreach ($packages as $package => $version) |
136 | { |
137 | try |
138 | { |
139 | if ($this->extension_manager->is_enabled($package)) |
140 | { |
141 | $this->enabled_extensions[] = $package; |
142 | $this->extension_manager->disable($package); |
143 | } |
144 | } |
145 | catch (\phpbb\exception\runtime_exception $e) |
146 | { |
147 | /** @psalm-suppress InvalidArgument */ |
148 | $io->writeError([[$e->getMessage(), $e->get_parameters(), 4]]); |
149 | } |
150 | catch (\Exception $e) |
151 | { |
152 | /** @psalm-suppress InvalidArgument */ |
153 | $io->writeError([[$e->getMessage(), [], 4]]); |
154 | } |
155 | } |
156 | } |
157 | |
158 | /** |
159 | * {@inheritdoc} |
160 | */ |
161 | protected function post_update(array $packages, IOInterface $io = null) |
162 | { |
163 | /** @psalm-suppress InvalidArgument */ |
164 | $io->writeError([['ENABLING_EXTENSIONS', [], 1]]); |
165 | foreach ($this->enabled_extensions as $package) |
166 | { |
167 | try |
168 | { |
169 | $this->extension_manager->enable($package); |
170 | } |
171 | catch (\phpbb\exception\runtime_exception $e) |
172 | { |
173 | /** @psalm-suppress InvalidArgument */ |
174 | $io->writeError([[$e->getMessage(), $e->get_parameters(), 4]]); |
175 | } |
176 | catch (\Exception $e) |
177 | { |
178 | /** @psalm-suppress InvalidArgument */ |
179 | $io->writeError([[$e->getMessage(), [], 4]]); |
180 | } |
181 | } |
182 | } |
183 | |
184 | /** |
185 | * {@inheritdoc} |
186 | */ |
187 | public function remove(array $packages, IOInterface $io = null) |
188 | { |
189 | $packages = $this->normalize_version($packages); |
190 | |
191 | $not_installed = array_diff(array_keys($packages), array_keys($this->extension_manager->all_available())); |
192 | if (count($not_installed) !== 0) |
193 | { |
194 | throw new runtime_exception($this->exception_prefix, 'NOT_INSTALLED', [implode('|', array_keys($not_installed))]); |
195 | } |
196 | |
197 | parent::remove($packages, $io); |
198 | } |
199 | |
200 | /** |
201 | * {@inheritdoc} |
202 | */ |
203 | public function pre_remove(array $packages, IOInterface $io = null) |
204 | { |
205 | if ($this->purge_on_remove) |
206 | { |
207 | /** @psalm-suppress InvalidArgument */ |
208 | $io->writeError([['DISABLING_EXTENSIONS', [], 1]]); |
209 | } |
210 | |
211 | foreach ($packages as $package => $version) |
212 | { |
213 | try |
214 | { |
215 | if ($this->extension_manager->is_enabled($package)) |
216 | { |
217 | if ($this->purge_on_remove) |
218 | { |
219 | $this->extension_manager->purge($package); |
220 | } |
221 | else |
222 | { |
223 | $this->extension_manager->disable($package); |
224 | } |
225 | } |
226 | } |
227 | catch (\phpbb\exception\runtime_exception $e) |
228 | { |
229 | /** @psalm-suppress InvalidArgument */ |
230 | $io->writeError([[$e->getMessage(), $e->get_parameters(), 4]]); |
231 | } |
232 | catch (\Exception $e) |
233 | { |
234 | /** @psalm-suppress InvalidArgument */ |
235 | $io->writeError([[$e->getMessage(), [], 4]]); |
236 | } |
237 | } |
238 | } |
239 | |
240 | /** |
241 | * {@inheritdoc} |
242 | */ |
243 | public function start_managing($package, $io) |
244 | { |
245 | if (!$this->extension_manager->is_available($package)) |
246 | { |
247 | throw new runtime_exception($this->exception_prefix, 'NOT_INSTALLED', [$package]); |
248 | } |
249 | |
250 | if ($this->is_managed($package)) |
251 | { |
252 | throw new runtime_exception($this->exception_prefix, 'ALREADY_MANAGED', [$package]); |
253 | } |
254 | |
255 | $enabled = false; |
256 | if ($this->extension_manager->is_enabled($package)) |
257 | { |
258 | $enabled = true; |
259 | /** @psalm-suppress InvalidArgument */ |
260 | $io->writeError([['DISABLING_EXTENSIONS', [], 1]]); |
261 | $this->extension_manager->disable($package); |
262 | } |
263 | |
264 | $ext_path = $this->extension_manager->get_extension_path($package, true); |
265 | $backup_path = rtrim($ext_path, '/') . '__backup__'; |
266 | |
267 | try |
268 | { |
269 | $this->filesystem->rename($ext_path, $backup_path); |
270 | } |
271 | catch (filesystem_exception $e) |
272 | { |
273 | throw new runtime_exception($this->exception_prefix, 'CANNOT_MANAGE_FILESYSTEM_ERROR', [$package], $e); |
274 | } |
275 | |
276 | try |
277 | { |
278 | $this->install((array) $package, $io); |
279 | $this->filesystem->remove($backup_path); |
280 | } |
281 | catch (runtime_exception $e) |
282 | { |
283 | $this->filesystem->rename($backup_path, $ext_path); |
284 | throw new runtime_exception($this->exception_prefix, 'CANNOT_MANAGE_INSTALL_ERROR', [$package], $e); |
285 | } |
286 | catch (filesystem_exception $e) |
287 | { |
288 | throw new managed_with_clean_error_exception($this->exception_prefix, 'MANAGED_WITH_CLEAN_ERROR', [$package, $backup_path], $e); |
289 | } |
290 | |
291 | if ($enabled) |
292 | { |
293 | try |
294 | { |
295 | /** @psalm-suppress InvalidArgument */ |
296 | $io->writeError([['ENABLING_EXTENSIONS', [], 1]]); |
297 | $this->extension_manager->enable($package); |
298 | } |
299 | catch (\Exception $e) |
300 | { |
301 | throw new managed_with_enable_error_exception($this->exception_prefix, 'MANAGED_WITH_ENABLE_ERROR', [$package], $e); |
302 | } |
303 | } |
304 | } |
305 | |
306 | /** |
307 | * {@inheritdoc} |
308 | */ |
309 | public function check_requirements() |
310 | { |
311 | return parent::check_requirements() && $this->filesystem->is_writable($this->root_path . 'ext/'); |
312 | } |
313 | |
314 | /** |
315 | * Enable the extensions when installing |
316 | * |
317 | * Warning: Only the explicitly required extensions will be enabled |
318 | * |
319 | * @param bool $enable |
320 | */ |
321 | public function set_enable_on_install($enable) |
322 | { |
323 | $this->enable_on_install = $enable; |
324 | } |
325 | |
326 | /** |
327 | * Purge the extension when disabling it |
328 | * |
329 | * @param bool $purge |
330 | */ |
331 | public function set_purge_on_remove($purge) |
332 | { |
333 | $this->purge_on_remove = $purge; |
334 | } |
335 | } |