This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the puli/manager package. |
||
5 | * |
||
6 | * (c) Bernhard Schussek <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace Puli\Manager\Module; |
||
13 | |||
14 | use Exception; |
||
15 | use InvalidArgumentException; |
||
16 | use Puli\Manager\Api\Context\ProjectContext; |
||
17 | use Puli\Manager\Api\Module\RootModuleFile; |
||
18 | use Puli\Manager\Api\Module\RootModuleFileManager; |
||
19 | use Puli\Manager\Config\AbstractConfigManager; |
||
20 | use Puli\Manager\Json\JsonStorage; |
||
21 | use ReflectionClass; |
||
22 | use ReflectionException; |
||
23 | use Webmozart\Expression\Expr; |
||
24 | use Webmozart\Expression\Expression; |
||
25 | |||
26 | /** |
||
27 | * Manages changes to the root module file. |
||
28 | * |
||
29 | * Use this class to make persistent changes to the puli.json of a project. |
||
30 | * Whenever you call methods in this class, the changes will be written to disk. |
||
31 | * |
||
32 | * @since 1.0 |
||
33 | * |
||
34 | * @author Bernhard Schussek <[email protected]> |
||
35 | */ |
||
36 | class RootModuleFileManagerImpl extends AbstractConfigManager implements RootModuleFileManager |
||
37 | { |
||
38 | /** |
||
39 | * @var ProjectContext |
||
40 | */ |
||
41 | private $context; |
||
42 | |||
43 | /** |
||
44 | * @var RootModuleFile |
||
45 | */ |
||
46 | private $rootModuleFile; |
||
47 | |||
48 | /** |
||
49 | * @var JsonStorage |
||
50 | */ |
||
51 | private $jsonStorage; |
||
52 | |||
53 | /** |
||
54 | * Creates a new module file manager. |
||
55 | * |
||
56 | * @param ProjectContext $context The project context |
||
57 | * @param JsonStorage $jsonStorage The module file storage. |
||
58 | */ |
||
59 | 80 | public function __construct(ProjectContext $context, JsonStorage $jsonStorage) |
|
60 | { |
||
61 | 80 | $this->context = $context; |
|
62 | 80 | $this->rootModuleFile = $context->getRootModuleFile(); |
|
63 | 80 | $this->jsonStorage = $jsonStorage; |
|
64 | 80 | } |
|
65 | |||
66 | /** |
||
67 | * {@inheritdoc} |
||
68 | */ |
||
69 | 17 | public function getConfig() |
|
70 | { |
||
71 | 17 | return $this->rootModuleFile->getConfig(); |
|
72 | } |
||
73 | |||
74 | /** |
||
75 | * {@inheritdoc} |
||
76 | */ |
||
77 | 1 | public function getContext() |
|
78 | { |
||
79 | 1 | return $this->context; |
|
80 | } |
||
81 | |||
82 | /** |
||
83 | * {@inheritdoc} |
||
84 | */ |
||
85 | public function getModuleFile() |
||
86 | { |
||
87 | return $this->rootModuleFile; |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * {@inheritdoc} |
||
92 | */ |
||
93 | 4 | public function getModuleName() |
|
94 | { |
||
95 | 4 | return $this->rootModuleFile->getModuleName(); |
|
96 | } |
||
97 | |||
98 | /** |
||
99 | * {@inheritdoc} |
||
100 | */ |
||
101 | 3 | View Code Duplication | public function setModuleName($moduleName) |
0 ignored issues
–
show
|
|||
102 | { |
||
103 | 3 | if ($moduleName === $this->rootModuleFile->getModuleName()) { |
|
104 | 1 | return; |
|
105 | } |
||
106 | |||
107 | 2 | $previousName = $this->rootModuleFile->getModuleName(); |
|
108 | |||
109 | 2 | $this->rootModuleFile->setModuleName($moduleName); |
|
110 | |||
111 | try { |
||
112 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
113 | 1 | } catch (Exception $e) { |
|
114 | 1 | $this->rootModuleFile->setModuleName($previousName); |
|
115 | |||
116 | 1 | throw $e; |
|
117 | } |
||
118 | 1 | } |
|
119 | |||
120 | /** |
||
121 | * {@inheritdoc} |
||
122 | */ |
||
123 | 8 | View Code Duplication | public function addPluginClass($pluginClass) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
124 | { |
||
125 | 8 | if ($this->rootModuleFile->hasPluginClass($pluginClass)) { |
|
126 | // Already installed locally |
||
127 | 1 | return; |
|
128 | } |
||
129 | |||
130 | 7 | $this->validatePluginClass($pluginClass); |
|
131 | |||
132 | 2 | $previousClasses = $this->rootModuleFile->getPluginClasses(); |
|
133 | |||
134 | 2 | $this->rootModuleFile->addPluginClass($pluginClass); |
|
135 | |||
136 | try { |
||
137 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
138 | 1 | } catch (Exception $e) { |
|
139 | 1 | $this->rootModuleFile->setPluginClasses($previousClasses); |
|
140 | |||
141 | 1 | throw $e; |
|
142 | } |
||
143 | 1 | } |
|
144 | |||
145 | /** |
||
146 | * {@inheritdoc} |
||
147 | */ |
||
148 | 3 | public function removePluginClass($pluginClass) |
|
149 | { |
||
150 | 3 | if (!$this->rootModuleFile->hasPluginClass($pluginClass)) { |
|
151 | 1 | return; |
|
152 | } |
||
153 | |||
154 | 2 | $previousClasses = $this->rootModuleFile->getPluginClasses(); |
|
155 | |||
156 | 2 | $this->rootModuleFile->removePluginClass($pluginClass); |
|
157 | |||
158 | try { |
||
159 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
160 | 1 | } catch (Exception $e) { |
|
161 | 1 | $this->rootModuleFile->setPluginClasses($previousClasses); |
|
162 | |||
163 | 1 | throw $e; |
|
164 | } |
||
165 | 1 | } |
|
166 | |||
167 | /** |
||
168 | * {@inheritdoc} |
||
169 | */ |
||
170 | 7 | View Code Duplication | public function removePluginClasses(Expression $expr) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
171 | { |
||
172 | 7 | $save = false; |
|
173 | 7 | $previousClasses = $this->rootModuleFile->getPluginClasses(); |
|
174 | |||
175 | 7 | foreach ($previousClasses as $pluginClass) { |
|
176 | 6 | if ($expr->evaluate($pluginClass)) { |
|
177 | 5 | $this->rootModuleFile->removePluginClass($pluginClass); |
|
178 | 6 | $save = true; |
|
179 | } |
||
180 | } |
||
181 | |||
182 | 7 | if (!$save) { |
|
183 | 2 | return; |
|
184 | } |
||
185 | |||
186 | try { |
||
187 | 5 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
188 | 2 | } catch (Exception $e) { |
|
189 | 2 | $this->rootModuleFile->setPluginClasses($previousClasses); |
|
190 | |||
191 | 2 | throw $e; |
|
192 | } |
||
193 | 3 | } |
|
194 | |||
195 | /** |
||
196 | * {@inheritdoc} |
||
197 | */ |
||
198 | 3 | public function clearPluginClasses() |
|
199 | { |
||
200 | 3 | $this->removePluginClasses(Expr::true()); |
|
201 | 2 | } |
|
202 | |||
203 | /** |
||
204 | * {@inheritdoc} |
||
205 | */ |
||
206 | 1 | public function hasPluginClass($pluginClass) |
|
207 | { |
||
208 | 1 | return $this->rootModuleFile->hasPluginClass($pluginClass); |
|
209 | } |
||
210 | |||
211 | /** |
||
212 | * {@inheritdoc} |
||
213 | */ |
||
214 | 1 | View Code Duplication | public function hasPluginClasses(Expression $expr = null) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
215 | { |
||
216 | 1 | if (!$expr) { |
|
217 | 1 | return $this->rootModuleFile->hasPluginClasses(); |
|
218 | } |
||
219 | |||
220 | 1 | foreach ($this->rootModuleFile->getPluginClasses() as $pluginClass) { |
|
221 | 1 | if ($expr->evaluate($pluginClass)) { |
|
222 | 1 | return true; |
|
223 | } |
||
224 | } |
||
225 | |||
226 | 1 | return false; |
|
227 | } |
||
228 | |||
229 | /** |
||
230 | * {@inheritdoc} |
||
231 | */ |
||
232 | 14 | public function getPluginClasses() |
|
233 | { |
||
234 | 14 | return $this->rootModuleFile->getPluginClasses(); |
|
235 | } |
||
236 | |||
237 | /** |
||
238 | * {@inheritdoc} |
||
239 | */ |
||
240 | 1 | public function findPluginClasses(Expression $expr) |
|
241 | { |
||
242 | 1 | $pluginClasses = array(); |
|
243 | |||
244 | 1 | foreach ($this->rootModuleFile->getPluginClasses() as $pluginClass) { |
|
245 | 1 | if ($expr->evaluate($pluginClass)) { |
|
246 | 1 | $pluginClasses[] = $pluginClass; |
|
247 | } |
||
248 | } |
||
249 | |||
250 | 1 | return $pluginClasses; |
|
251 | } |
||
252 | |||
253 | /** |
||
254 | * {@inheritdoc} |
||
255 | */ |
||
256 | 4 | public function setExtraKey($key, $value) |
|
257 | { |
||
258 | 4 | $previouslySet = $this->rootModuleFile->hasExtraKey($key); |
|
259 | 4 | $previousValue = $this->rootModuleFile->getExtraKey($key); |
|
260 | |||
261 | 4 | if ($value === $previousValue) { |
|
262 | 1 | return; |
|
263 | } |
||
264 | |||
265 | 3 | $this->rootModuleFile->setExtraKey($key, $value); |
|
266 | |||
267 | try { |
||
268 | 3 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
269 | 2 | } catch (Exception $e) { |
|
270 | 2 | if ($previouslySet) { |
|
271 | 1 | $this->rootModuleFile->setExtraKey($key, $previousValue); |
|
272 | } else { |
||
273 | 1 | $this->rootModuleFile->removeExtraKey($key); |
|
274 | } |
||
275 | |||
276 | 2 | throw $e; |
|
277 | } |
||
278 | 1 | } |
|
279 | |||
280 | /** |
||
281 | * {@inheritdoc} |
||
282 | */ |
||
283 | 3 | public function setExtraKeys(array $values) |
|
284 | { |
||
285 | 3 | $previousValues = array(); |
|
286 | 3 | $previouslyUnset = array(); |
|
287 | |||
288 | 3 | foreach ($values as $key => $value) { |
|
289 | 3 | if ($this->rootModuleFile->hasExtraKey($key)) { |
|
290 | 2 | if ($value !== $previous = $this->rootModuleFile->getExtraKey($key)) { |
|
291 | 2 | $previousValues[$key] = $previous; |
|
292 | } |
||
293 | } else { |
||
294 | 3 | $previouslyUnset[$key] = true; |
|
295 | } |
||
296 | } |
||
297 | |||
298 | 3 | if (!$previousValues && !$previouslyUnset) { |
|
0 ignored issues
–
show
The expression
$previousValues of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() The expression
$previouslyUnset of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
299 | 1 | return; |
|
300 | } |
||
301 | |||
302 | 2 | $this->rootModuleFile->setExtraKeys($values); |
|
303 | |||
304 | try { |
||
305 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
306 | 1 | } catch (Exception $e) { |
|
307 | 1 | foreach ($values as $key => $value) { |
|
308 | 1 | if (isset($previouslyUnset[$key])) { |
|
309 | 1 | $this->rootModuleFile->removeExtraKey($key); |
|
310 | } else { |
||
311 | 1 | $this->rootModuleFile->setExtraKey($key, $previousValues[$key]); |
|
312 | } |
||
313 | } |
||
314 | |||
315 | 1 | throw $e; |
|
316 | } |
||
317 | 1 | } |
|
318 | |||
319 | /** |
||
320 | * {@inheritdoc} |
||
321 | */ |
||
322 | 3 | View Code Duplication | public function removeExtraKey($key) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
323 | { |
||
324 | 3 | if (!$this->rootModuleFile->hasExtraKey($key)) { |
|
325 | 1 | return; |
|
326 | } |
||
327 | |||
328 | 2 | $previousValue = $this->rootModuleFile->getExtraKey($key); |
|
329 | |||
330 | 2 | $this->rootModuleFile->removeExtraKey($key); |
|
331 | |||
332 | try { |
||
333 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
334 | 1 | } catch (Exception $e) { |
|
335 | 1 | $this->rootModuleFile->setExtraKey($key, $previousValue); |
|
336 | |||
337 | 1 | throw $e; |
|
338 | } |
||
339 | 1 | } |
|
340 | |||
341 | /** |
||
342 | * {@inheritdoc} |
||
343 | */ |
||
344 | 3 | View Code Duplication | public function removeExtraKeys(Expression $expr) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
345 | { |
||
346 | 3 | $previousValues = $this->rootModuleFile->getExtraKeys(); |
|
347 | 3 | $save = false; |
|
348 | |||
349 | 3 | foreach ($this->rootModuleFile->getExtraKeys() as $key => $value) { |
|
350 | 2 | if ($expr->evaluate($key)) { |
|
351 | 2 | $this->rootModuleFile->removeExtraKey($key); |
|
352 | 2 | $save = true; |
|
353 | } |
||
354 | } |
||
355 | |||
356 | 3 | if (!$save) { |
|
357 | 1 | return; |
|
358 | } |
||
359 | |||
360 | try { |
||
361 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
362 | 1 | } catch (Exception $e) { |
|
363 | 1 | $this->rootModuleFile->setExtraKeys($previousValues); |
|
364 | |||
365 | 1 | throw $e; |
|
366 | } |
||
367 | 1 | } |
|
368 | |||
369 | /** |
||
370 | * {@inheritdoc} |
||
371 | */ |
||
372 | 3 | View Code Duplication | public function clearExtraKeys() |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
373 | { |
||
374 | 3 | $previousValues = $this->rootModuleFile->getExtraKeys(); |
|
375 | |||
376 | 3 | if (!$previousValues) { |
|
0 ignored issues
–
show
The expression
$previousValues of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
377 | 1 | return; |
|
378 | } |
||
379 | |||
380 | 2 | $this->rootModuleFile->clearExtraKeys(); |
|
381 | |||
382 | try { |
||
383 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
384 | 1 | } catch (Exception $e) { |
|
385 | 1 | $this->rootModuleFile->setExtraKeys($previousValues); |
|
386 | |||
387 | 1 | throw $e; |
|
388 | } |
||
389 | 1 | } |
|
390 | |||
391 | /** |
||
392 | * {@inheritdoc} |
||
393 | */ |
||
394 | 1 | public function hasExtraKey($key) |
|
395 | { |
||
396 | 1 | return $this->rootModuleFile->hasExtraKey($key); |
|
397 | } |
||
398 | |||
399 | /** |
||
400 | * {@inheritdoc} |
||
401 | */ |
||
402 | 1 | View Code Duplication | public function hasExtraKeys(Expression $expr = null) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
403 | { |
||
404 | 1 | if (!$expr) { |
|
405 | 1 | return $this->rootModuleFile->hasExtraKeys(); |
|
406 | } |
||
407 | |||
408 | 1 | foreach ($this->rootModuleFile->getExtraKeys() as $key => $value) { |
|
409 | 1 | if ($expr->evaluate($key)) { |
|
410 | 1 | return true; |
|
411 | } |
||
412 | } |
||
413 | |||
414 | 1 | return false; |
|
415 | } |
||
416 | |||
417 | /** |
||
418 | * {@inheritdoc} |
||
419 | */ |
||
420 | 15 | public function getExtraKey($key, $default = null) |
|
421 | { |
||
422 | 15 | return $this->rootModuleFile->getExtraKey($key, $default); |
|
423 | } |
||
424 | |||
425 | /** |
||
426 | * {@inheritdoc} |
||
427 | */ |
||
428 | 1 | public function getExtraKeys() |
|
429 | { |
||
430 | 1 | return $this->rootModuleFile->getExtraKeys(); |
|
431 | } |
||
432 | |||
433 | /** |
||
434 | * {@inheritdoc} |
||
435 | */ |
||
436 | 1 | public function findExtraKeys(Expression $expr) |
|
437 | { |
||
438 | 1 | $values = array(); |
|
439 | |||
440 | 1 | foreach ($this->rootModuleFile->getExtraKeys() as $key => $value) { |
|
441 | 1 | if ($expr->evaluate($key)) { |
|
442 | 1 | $values[$key] = $value; |
|
443 | } |
||
444 | } |
||
445 | |||
446 | 1 | return $values; |
|
447 | } |
||
448 | |||
449 | /** |
||
450 | * {@inheritdoc} |
||
451 | */ |
||
452 | 2 | View Code Duplication | public function migrate($targetVersion) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
453 | { |
||
454 | 2 | $previousVersion = $this->rootModuleFile->getVersion(); |
|
455 | |||
456 | 2 | if ($previousVersion === $targetVersion) { |
|
457 | return; |
||
458 | } |
||
459 | |||
460 | 2 | $this->rootModuleFile->setVersion($targetVersion); |
|
461 | |||
462 | try { |
||
463 | 2 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
464 | 1 | } catch (Exception $e) { |
|
465 | 1 | $this->rootModuleFile->setVersion($previousVersion); |
|
466 | |||
467 | 1 | throw $e; |
|
468 | } |
||
469 | 1 | } |
|
470 | |||
471 | /** |
||
472 | * {@inheritdoc} |
||
473 | */ |
||
474 | 4 | protected function saveConfigFile() |
|
475 | { |
||
476 | 4 | $this->jsonStorage->saveRootModuleFile($this->rootModuleFile); |
|
477 | 4 | } |
|
478 | |||
479 | 7 | private function validatePluginClass($pluginClass) |
|
480 | { |
||
481 | try { |
||
482 | 7 | $reflClass = new ReflectionClass($pluginClass); |
|
483 | 1 | } catch (ReflectionException $e) { |
|
484 | 1 | throw new InvalidArgumentException(sprintf( |
|
485 | 1 | 'The plugin class %s does not exist.', |
|
486 | $pluginClass |
||
487 | 1 | ), 0, $e); |
|
488 | } |
||
489 | |||
490 | 6 | if ($reflClass->isInterface()) { |
|
491 | 1 | throw new InvalidArgumentException(sprintf( |
|
492 | 1 | 'The plugin class %s should be a class, but is an interface.', |
|
493 | $pluginClass |
||
494 | )); |
||
495 | } |
||
496 | |||
497 | 5 | if (version_compare(PHP_VERSION, '5.4.0', '>=') && $reflClass->isTrait()) { |
|
498 | 1 | throw new InvalidArgumentException(sprintf( |
|
499 | 1 | 'The plugin class %s should be a class, but is a trait.', |
|
500 | $pluginClass |
||
501 | )); |
||
502 | } |
||
503 | |||
504 | 4 | if (!$reflClass->implementsInterface('\Puli\Manager\Api\PuliPlugin')) { |
|
505 | 1 | throw new InvalidArgumentException(sprintf( |
|
506 | 1 | 'The plugin class %s must implement PuliPlugin.', |
|
507 | $pluginClass |
||
508 | )); |
||
509 | } |
||
510 | |||
511 | 3 | $constructor = $reflClass->getConstructor(); |
|
512 | |||
513 | 3 | if (null !== $constructor && $constructor->getNumberOfRequiredParameters() > 0) { |
|
514 | 1 | throw new InvalidArgumentException(sprintf( |
|
515 | 'The constructor of the plugin class %s must not have required '. |
||
516 | 1 | 'parameters.', |
|
517 | $pluginClass |
||
518 | )); |
||
519 | } |
||
520 | 2 | } |
|
521 | } |
||
522 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.