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/composer-plugin 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\ComposerPlugin; |
||
13 | |||
14 | use Composer\Composer; |
||
15 | use Composer\Config; |
||
16 | use Composer\IO\IOInterface; |
||
17 | use Composer\Package\AliasPackage; |
||
18 | use Composer\Package\PackageInterface; |
||
19 | use Composer\Script\Event; |
||
20 | use Exception; |
||
21 | use RuntimeException; |
||
22 | use Symfony\Component\Filesystem\Filesystem; |
||
23 | use Webmozart\PathUtil\Path; |
||
24 | |||
25 | /** |
||
26 | * Implementation of the Puli plugin. |
||
27 | * |
||
28 | * This class is separate from the main {@link PuliPlugin} class so that it can |
||
29 | * be loaded lazily after updating the sources of this package in the project |
||
30 | * that requires the package. |
||
31 | * |
||
32 | * @author Bernhard Schussek <[email protected]> |
||
33 | */ |
||
34 | class PuliPluginImpl |
||
35 | { |
||
36 | /** |
||
37 | * The version of the Puli plugin. |
||
38 | */ |
||
39 | const VERSION = '@package_version@'; |
||
40 | |||
41 | /** |
||
42 | * The minimum version of the Puli CLI. |
||
43 | */ |
||
44 | const MIN_CLI_VERSION = '1.0.0-beta10'; |
||
45 | |||
46 | /** |
||
47 | * The maximum version of the Puli CLI. |
||
48 | */ |
||
49 | const MAX_CLI_VERSION = '1.999.99999'; |
||
50 | |||
51 | /** |
||
52 | * The name of the installer. |
||
53 | */ |
||
54 | const INSTALLER_NAME = 'composer'; |
||
55 | |||
56 | /** |
||
57 | * @var Composer |
||
58 | */ |
||
59 | private $composer; |
||
60 | |||
61 | /** |
||
62 | * @var IOInterface |
||
63 | */ |
||
64 | private $io; |
||
65 | |||
66 | /** |
||
67 | * @var Config |
||
68 | */ |
||
69 | private $config; |
||
70 | |||
71 | /** |
||
72 | * @var bool |
||
73 | */ |
||
74 | private $isDev; |
||
75 | |||
76 | /** |
||
77 | * @var PuliRunner |
||
78 | */ |
||
79 | private $puliRunner; |
||
80 | |||
81 | /** |
||
82 | * @var string |
||
83 | */ |
||
84 | private $rootDir; |
||
85 | |||
86 | /** |
||
87 | * @var bool |
||
88 | */ |
||
89 | private $runPreAutoloadDump = true; |
||
90 | |||
91 | /** |
||
92 | * @var bool |
||
93 | */ |
||
94 | private $runPostAutoloadDump = true; |
||
95 | |||
96 | /** |
||
97 | * @var bool |
||
98 | */ |
||
99 | private $runPostInstall = true; |
||
100 | |||
101 | /** |
||
102 | * @var bool |
||
103 | */ |
||
104 | private $initialized = false; |
||
105 | |||
106 | /** |
||
107 | * @var string |
||
108 | */ |
||
109 | private $autoloadFile; |
||
110 | |||
111 | 42 | public function __construct(Event $event, PuliRunner $puliRunner = null) |
|
112 | { |
||
113 | 42 | $this->composer = $event->getComposer(); |
|
114 | 42 | $this->io = $event->getIO(); |
|
115 | 42 | $this->config = $this->composer->getConfig(); |
|
116 | 42 | $this->isDev = $event->isDevMode(); |
|
117 | 42 | $this->puliRunner = $puliRunner; |
|
118 | 42 | $this->rootDir = Path::normalize(getcwd()); |
|
119 | |||
120 | 42 | $vendorDir = $this->config->get('vendor-dir'); |
|
121 | |||
122 | // On TravisCI, $vendorDir is a relative path. Probably an old Composer |
||
123 | // build or something. Usually, $vendorDir should be absolute already. |
||
124 | 42 | $vendorDir = Path::makeAbsolute($vendorDir, $this->rootDir); |
|
125 | |||
126 | 42 | $this->autoloadFile = $vendorDir.'/autoload.php'; |
|
127 | 42 | } |
|
128 | |||
129 | 3 | public function preAutoloadDump() |
|
130 | { |
||
131 | 3 | if (!$this->initialized) { |
|
132 | 3 | $this->initialize(); |
|
133 | } |
||
134 | |||
135 | // This method is called twice. Run it only once. |
||
136 | 3 | if (!$this->runPreAutoloadDump) { |
|
137 | return; |
||
138 | } |
||
139 | |||
140 | 3 | $this->runPreAutoloadDump = false; |
|
141 | |||
142 | try { |
||
143 | 3 | $factoryClass = $this->getConfigKey('factory.in.class'); |
|
144 | 3 | $factoryFile = $this->getConfigKey('factory.in.file'); |
|
145 | } catch (PuliRunnerException $e) { |
||
146 | $this->printWarning('Could not load Puli configuration', $e); |
||
147 | |||
148 | return; |
||
149 | } |
||
150 | |||
151 | 3 | $factoryFile = Path::makeAbsolute($factoryFile, $this->rootDir); |
|
0 ignored issues
–
show
|
|||
152 | |||
153 | 3 | $autoload = $this->composer->getPackage()->getAutoload(); |
|
154 | 3 | $autoload['classmap'][] = $factoryFile; |
|
155 | |||
156 | 3 | $this->composer->getPackage()->setAutoload($autoload); |
|
157 | |||
158 | 3 | if (!file_exists($factoryFile)) { |
|
159 | 2 | $filesystem = new Filesystem(); |
|
160 | // Let Composer find the factory class with a temporary stub |
||
161 | |||
162 | 2 | $namespace = explode('\\', ltrim($factoryClass, '\\')); |
|
163 | 2 | $className = array_pop($namespace); |
|
164 | |||
165 | 2 | if (count($namespace)) { |
|
166 | 1 | $stub = '<?php namespace '.implode('\\', $namespace).'; class '.$className.' {}'; |
|
167 | } else { |
||
168 | 1 | $stub = '<?php class '.$className.' {}'; |
|
169 | } |
||
170 | |||
171 | 2 | $filesystem->dumpFile($factoryFile, $stub); |
|
172 | } |
||
173 | 3 | } |
|
174 | |||
175 | 5 | public function postAutoloadDump() |
|
176 | { |
||
177 | 5 | if (!$this->initialized) { |
|
178 | 5 | $this->initialize(); |
|
179 | } |
||
180 | |||
181 | // This method is called twice. Run it only once. |
||
182 | 5 | if (!$this->runPostAutoloadDump) { |
|
183 | 1 | return; |
|
184 | } |
||
185 | |||
186 | 5 | $this->runPostAutoloadDump = false; |
|
187 | |||
188 | try { |
||
189 | 5 | $factoryClass = $this->getConfigKey('factory.in.class'); |
|
190 | 1 | } catch (PuliRunnerException $e) { |
|
191 | 1 | $this->printWarning('Could not load Puli configuration', $e); |
|
192 | |||
193 | 1 | return; |
|
194 | } |
||
195 | |||
196 | 4 | $this->insertFactoryClassConstant($this->autoloadFile, $factoryClass); |
|
197 | 4 | $this->setBootstrapFile($this->autoloadFile); |
|
198 | 4 | } |
|
199 | |||
200 | /** |
||
201 | * Updates the Puli repository after Composer installations/updates. |
||
202 | */ |
||
203 | 34 | public function postInstall() |
|
204 | { |
||
205 | 34 | if (!$this->initialized) { |
|
206 | 34 | $this->initialize(); |
|
207 | } |
||
208 | |||
209 | // This method is called twice. Run it only once. |
||
210 | 34 | if (!$this->runPostInstall) { |
|
211 | 3 | return; |
|
212 | } |
||
213 | |||
214 | 32 | $this->runPostInstall = false; |
|
215 | |||
216 | 32 | $this->io->write('<info>Synchronizing Puli with Composer</info>'); |
|
217 | |||
218 | 32 | $rootPackage = $this->composer->getPackage(); |
|
219 | 32 | $composerPackages = $this->loadComposerPackages(); |
|
220 | 32 | $prodPackageNames = $this->filterProdPackageNames($composerPackages, $rootPackage); |
|
221 | 32 | $env = $this->isDev ? PuliPackage::ENV_DEV : PuliPackage::ENV_PROD; |
|
222 | |||
223 | try { |
||
224 | 32 | $puliPackages = $this->loadPuliPackages(); |
|
225 | 1 | } catch (PuliRunnerException $e) { |
|
226 | 1 | $this->printWarning('Could not load Puli packages', $e); |
|
227 | |||
228 | 1 | return; |
|
229 | } |
||
230 | |||
231 | // Don't remove non-existing packages in production environment |
||
232 | // Removed packages could be dev dependencies (i.e. "require-dev" |
||
233 | // of the root package or "require" of another dev dependency), and |
||
234 | // we can't find out whether they are since Composer doesn't load them |
||
235 | 31 | if (PuliPackage::ENV_PROD !== $env) { |
|
236 | 3 | $this->removeRemovedPackages($composerPackages, $puliPackages); |
|
237 | } |
||
238 | |||
239 | 31 | $this->installNewPackages($composerPackages, $prodPackageNames, $puliPackages); |
|
240 | |||
241 | // Don't print warnings for non-existing packages in production |
||
242 | 31 | if (PuliPackage::ENV_PROD !== $env) { |
|
243 | 3 | $this->checkForNotFoundErrors($puliPackages); |
|
244 | } |
||
245 | |||
246 | 31 | $this->checkForNotLoadableErrors($puliPackages); |
|
247 | 31 | $this->adoptComposerName($puliPackages); |
|
248 | 31 | $this->removePuliDir(); |
|
249 | 31 | $this->buildPuli(); |
|
250 | 31 | } |
|
251 | |||
252 | 42 | private function initialize() |
|
253 | { |
||
254 | 42 | if (!file_exists($this->autoloadFile)) { |
|
255 | $filesystem = new Filesystem(); |
||
256 | // Avoid problems if using the runner before autoload.php has been |
||
257 | // generated |
||
258 | $filesystem->dumpFile($this->autoloadFile, ''); |
||
259 | } |
||
260 | |||
261 | 42 | $this->initialized = true; |
|
262 | |||
263 | // Keep the manually set runner |
||
264 | 42 | if (null === $this->puliRunner) { |
|
265 | try { |
||
266 | // Add Composer's bin directory in case the "puli" executable is |
||
267 | // installed with Composer |
||
268 | $this->puliRunner = new PuliRunner($this->config->get('bin-dir')); |
||
269 | } catch (RuntimeException $e) { |
||
270 | $this->printWarning('Plugin initialization failed', $e); |
||
271 | $this->runPreAutoloadDump = false; |
||
272 | $this->runPostAutoloadDump = false; |
||
273 | $this->runPostInstall = false; |
||
274 | } |
||
275 | } |
||
276 | |||
277 | // Use the runner to verify if Puli has the right version |
||
278 | try { |
||
279 | 42 | $this->verifyPuliVersion(); |
|
280 | 2 | } catch (RuntimeException $e) { |
|
281 | 2 | $this->printWarning('Version check failed', $e); |
|
282 | 2 | $this->runPreAutoloadDump = false; |
|
283 | 2 | $this->runPostAutoloadDump = false; |
|
284 | 2 | $this->runPostInstall = false; |
|
285 | } |
||
286 | 42 | } |
|
287 | |||
288 | /** |
||
289 | * @param PackageInterface[] $composerPackages |
||
290 | * @param bool[] $prodPackageNames |
||
291 | * @param PuliPackage[] $puliPackages |
||
292 | */ |
||
293 | 31 | private function installNewPackages(array $composerPackages, array $prodPackageNames, array &$puliPackages) |
|
294 | { |
||
295 | 31 | $installationManager = $this->composer->getInstallationManager(); |
|
296 | |||
297 | 31 | foreach ($composerPackages as $packageName => $package) { |
|
298 | 21 | if ($package instanceof AliasPackage) { |
|
299 | 2 | $package = $package->getAliasOf(); |
|
300 | } |
||
301 | |||
302 | // We need to normalize the system-dependent paths returned by Composer |
||
303 | 21 | $installPath = Path::normalize($installationManager->getInstallPath($package)); |
|
304 | 21 | $env = isset($prodPackageNames[$packageName]) ? PuliPackage::ENV_PROD : PuliPackage::ENV_DEV; |
|
305 | |||
306 | // Skip meta packages |
||
307 | 21 | if ('' === $installPath) { |
|
308 | 1 | continue; |
|
309 | } |
||
310 | |||
311 | 20 | if (isset($puliPackages[$packageName])) { |
|
312 | 15 | $puliPackage = $puliPackages[$packageName]; |
|
313 | |||
314 | // Only proceed if the install path or environment has changed |
||
315 | 15 | if ($installPath === $puliPackage->getInstallPath() && $env === $puliPackage->getEnvironment()) { |
|
316 | 14 | continue; |
|
317 | } |
||
318 | |||
319 | // Only remove packages installed by Composer |
||
320 | 6 | if (self::INSTALLER_NAME === $puliPackage->getInstallerName()) { |
|
321 | 5 | $this->io->write(sprintf( |
|
322 | 5 | 'Reinstalling <info>%s</info> (<comment>%s</comment>) in <comment>%s</comment>', |
|
323 | $packageName, |
||
324 | 5 | Path::makeRelative($installPath, $this->rootDir), |
|
325 | $env |
||
326 | )); |
||
327 | |||
328 | try { |
||
329 | 5 | $this->removePackage($packageName); |
|
330 | 1 | } catch (PuliRunnerException $e) { |
|
331 | 1 | $this->printPackageWarning('Could not remove package "%s" (at "%s")', $packageName, $installPath, $e); |
|
332 | |||
333 | 6 | continue; |
|
334 | } |
||
335 | } |
||
336 | } else { |
||
337 | 6 | $this->io->write(sprintf( |
|
338 | 6 | 'Installing <info>%s</info> (<comment>%s</comment>) in <comment>%s</comment>', |
|
339 | $packageName, |
||
340 | 6 | Path::makeRelative($installPath, $this->rootDir), |
|
341 | $env |
||
342 | )); |
||
343 | } |
||
344 | |||
345 | try { |
||
346 | 11 | $this->installPackage($installPath, $packageName, $env); |
|
347 | 3 | } catch (PuliRunnerException $e) { |
|
348 | 3 | $this->printPackageWarning('Could not install package "%s" (at "%s")', $packageName, $installPath, $e); |
|
349 | |||
350 | 3 | continue; |
|
351 | } |
||
352 | |||
353 | 8 | $puliPackages[$packageName] = new PuliPackage( |
|
354 | $packageName, |
||
355 | 8 | self::INSTALLER_NAME, |
|
356 | $installPath, |
||
357 | 8 | PuliPackage::STATE_ENABLED, |
|
358 | $env |
||
359 | ); |
||
360 | } |
||
361 | 31 | } |
|
362 | |||
363 | /** |
||
364 | * @param PackageInterface[] $composerPackages |
||
365 | * @param PuliPackage[] $puliPackages |
||
366 | */ |
||
367 | 3 | private function removeRemovedPackages(array $composerPackages, array &$puliPackages) |
|
368 | { |
||
369 | /** @var PuliPackage[] $notFoundPackages */ |
||
370 | $notFoundPackages = array_filter($puliPackages, function (PuliPackage $package) { |
||
371 | 3 | return PuliPackage::STATE_NOT_FOUND === $package->getState() |
|
372 | 3 | && PuliPluginImpl::INSTALLER_NAME === $package->getInstallerName(); |
|
373 | 3 | }); |
|
374 | |||
375 | 3 | foreach ($notFoundPackages as $packageName => $package) { |
|
376 | // Check whether package was only moved |
||
377 | 3 | if (isset($composerPackages[$packageName])) { |
|
378 | 1 | continue; |
|
379 | } |
||
380 | |||
381 | 2 | $this->io->write(sprintf( |
|
382 | 2 | 'Removing <info>%s</info> (<comment>%s</comment>)', |
|
383 | $packageName, |
||
384 | 2 | Path::makeRelative($package->getInstallPath(), $this->rootDir) |
|
385 | )); |
||
386 | |||
387 | try { |
||
388 | 2 | $this->removePackage($packageName); |
|
389 | 1 | } catch (PuliRunnerException $e) { |
|
390 | 1 | $this->printPackageWarning('Could not remove package "%s" (at "%s")', $packageName, $package->getInstallPath(), $e); |
|
391 | |||
392 | 1 | continue; |
|
393 | } |
||
394 | |||
395 | 1 | unset($puliPackages[$packageName]); |
|
396 | } |
||
397 | 3 | } |
|
398 | |||
399 | 3 | View Code Duplication | private function checkForNotFoundErrors(array $puliPackages) |
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. ![]() |
|||
400 | { |
||
401 | /** @var PuliPackage[] $notFoundPackages */ |
||
402 | 3 | $notFoundPackages = array_filter($puliPackages, |
|
403 | function (PuliPackage $package) { |
||
404 | 3 | return PuliPackage::STATE_NOT_FOUND === $package->getState() |
|
405 | 3 | && PuliPluginImpl::INSTALLER_NAME === $package->getInstallerName(); |
|
406 | 3 | }); |
|
407 | |||
408 | 3 | foreach ($notFoundPackages as $package) { |
|
409 | 2 | $this->printPackageWarning( |
|
410 | 2 | 'The package "%s" (at "%s") could not be found', |
|
411 | 2 | $package->getName(), |
|
412 | 2 | $package->getInstallPath() |
|
413 | ); |
||
414 | } |
||
415 | 3 | } |
|
416 | |||
417 | 31 | View Code Duplication | private function checkForNotLoadableErrors(array $puliPackages) |
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. ![]() |
|||
418 | { |
||
419 | /** @var PuliPackage[] $notLoadablePackages */ |
||
420 | $notLoadablePackages = array_filter($puliPackages, function (PuliPackage $package) { |
||
421 | 31 | return PuliPackage::STATE_NOT_LOADABLE === $package->getState() |
|
422 | 31 | && PuliPluginImpl::INSTALLER_NAME === $package->getInstallerName(); |
|
423 | 31 | }); |
|
424 | |||
425 | 31 | foreach ($notLoadablePackages as $package) { |
|
426 | 1 | $this->printPackageWarning( |
|
427 | 1 | 'The package "%s" (at "%s") could not be loaded', |
|
428 | 1 | $package->getName(), |
|
429 | 1 | $package->getInstallPath() |
|
430 | ); |
||
431 | } |
||
432 | 31 | } |
|
433 | |||
434 | 31 | private function adoptComposerName(array $puliPackages) |
|
435 | { |
||
436 | 31 | $rootDir = $this->rootDir; |
|
437 | |||
438 | /** @var PuliPackage[] $rootPackages */ |
||
439 | 31 | $rootPackages = array_filter($puliPackages, function (PuliPackage $package) use ($rootDir) { |
|
440 | 31 | return !$package->getInstallerName() && $rootDir === $package->getInstallPath(); |
|
441 | 31 | }); |
|
442 | |||
443 | 31 | if (0 === count($rootPackages)) { |
|
444 | // This should never happen |
||
445 | $this->printWarning('No root package could be found'); |
||
446 | |||
447 | return; |
||
448 | } |
||
449 | |||
450 | 31 | if (count($rootPackages) > 1) { |
|
451 | // This should never happen |
||
452 | $this->printWarning('More than one root package was found'); |
||
453 | |||
454 | return; |
||
455 | } |
||
456 | |||
457 | /** @var PuliPackage $rootPackage */ |
||
458 | 31 | $rootPackage = reset($rootPackages); |
|
459 | 31 | $name = $rootPackage->getName(); |
|
460 | 31 | $newName = $this->composer->getPackage()->getName(); |
|
461 | |||
462 | // Rename the root package after changing the name in composer.json |
||
463 | 31 | if ($name !== $newName) { |
|
464 | try { |
||
465 | 2 | $this->renamePackage($name, $newName); |
|
466 | 1 | } catch (PuliRunnerException $e) { |
|
467 | 1 | $this->printWarning(sprintf( |
|
468 | 1 | 'Could not rename root package to "%s"', |
|
469 | $newName |
||
470 | ), $e); |
||
471 | } |
||
472 | } |
||
473 | 31 | } |
|
474 | |||
475 | 4 | private function insertFactoryClassConstant($autoloadFile, $factoryClass) |
|
476 | { |
||
477 | 4 | if (!file_exists($autoloadFile)) { |
|
478 | throw new PuliPluginException(sprintf( |
||
479 | 'Could not adjust autoloader: The file %s was not found.', |
||
480 | $autoloadFile |
||
481 | )); |
||
482 | } |
||
483 | |||
484 | 4 | $this->io->write('<info>Generating the "PULI_FACTORY_CLASS" constant</info>'); |
|
485 | |||
486 | 4 | $contents = file_get_contents($autoloadFile); |
|
487 | 4 | $escFactoryClass = var_export($factoryClass, true); |
|
488 | 4 | $constant = "if (!defined('PULI_FACTORY_CLASS')) {\n"; |
|
489 | 4 | $constant .= sprintf(" define('PULI_FACTORY_CLASS', %s);\n", $escFactoryClass); |
|
490 | 4 | $constant .= "}\n\n"; |
|
491 | |||
492 | // Regex modifiers: |
||
493 | // "m": \s matches newlines |
||
494 | // "D": $ matches at EOF only |
||
495 | // Translation: insert before the last "return" in the file |
||
496 | 4 | $contents = preg_replace('/\n(?=return [^;]+;\s*$)/mD', "\n".$constant, |
|
497 | $contents); |
||
498 | |||
499 | 4 | file_put_contents($autoloadFile, $contents); |
|
500 | 4 | } |
|
501 | |||
502 | 4 | private function setBootstrapFile($autoloadFile) |
|
503 | { |
||
504 | 4 | $bootstrapFile = $this->getConfigKey('bootstrap-file'); |
|
505 | |||
506 | // Don't change user-defined bootstrap files |
||
507 | 4 | if (!empty($bootstrapFile)) { |
|
508 | 1 | return; |
|
509 | } |
||
510 | |||
511 | 3 | $relAutoloadFile = Path::makeRelative($autoloadFile, $this->rootDir); |
|
512 | |||
513 | 3 | $this->io->write(sprintf('<info>Setting "bootstrap-file" to "%s"</info>', $relAutoloadFile)); |
|
514 | |||
515 | 3 | $this->setConfigKey('bootstrap-file', $relAutoloadFile); |
|
516 | 3 | } |
|
517 | |||
518 | /** |
||
519 | * Loads Composer's currently installed packages. |
||
520 | * |
||
521 | * @return PackageInterface[] The installed packages indexed by their names. |
||
522 | */ |
||
523 | 32 | private function loadComposerPackages() |
|
524 | { |
||
525 | 32 | $repository = $this->composer->getRepositoryManager()->getLocalRepository(); |
|
526 | 32 | $packages = array(); |
|
527 | |||
528 | 32 | foreach ($repository->getPackages() as $package) { |
|
529 | /* @var PackageInterface $package */ |
||
530 | 21 | $packages[$package->getName()] = $package; |
|
531 | } |
||
532 | |||
533 | 32 | return $packages; |
|
534 | } |
||
535 | |||
536 | 39 | private function getConfigKey($key) |
|
537 | { |
||
538 | 39 | $value = trim($this->puliRunner->run('config %key% --parsed', array( |
|
539 | 39 | 'key' => $key, |
|
540 | ))); |
||
541 | |||
542 | switch ($value) { |
||
543 | 38 | case 'null': |
|
544 | 1 | return null; |
|
545 | 38 | case 'true': |
|
546 | return true; |
||
547 | 38 | case 'false': |
|
548 | return false; |
||
549 | default: |
||
550 | 38 | return $value; |
|
551 | } |
||
552 | } |
||
553 | |||
554 | 3 | private function setConfigKey($key, $value) |
|
555 | { |
||
556 | 3 | $this->puliRunner->run('config %key% %value%', array( |
|
557 | 3 | 'key' => $key, |
|
558 | 3 | 'value' => $value, |
|
559 | )); |
||
560 | 3 | } |
|
561 | |||
562 | /** |
||
563 | * @return PuliPackage[] |
||
564 | */ |
||
565 | 32 | private function loadPuliPackages() |
|
566 | { |
||
567 | 32 | $packages = array(); |
|
568 | |||
569 | 32 | $output = $this->puliRunner->run('package --list --format %format%', array( |
|
570 | 32 | 'format' => '%name%;%installer%;%install_path%;%state%;%env%', |
|
571 | )); |
||
572 | |||
573 | // PuliRunner replaces \r\n by \n for those Windows boxes |
||
574 | 31 | foreach (explode("\n", $output) as $packageLine) { |
|
575 | 31 | if (!$packageLine) { |
|
576 | 31 | continue; |
|
577 | } |
||
578 | |||
579 | 31 | $packageParts = explode(';', $packageLine); |
|
580 | |||
581 | 31 | $packages[$packageParts[0]] = new PuliPackage( |
|
582 | 31 | $packageParts[0], |
|
583 | 31 | $packageParts[1], |
|
584 | 31 | $packageParts[2], |
|
585 | 31 | $packageParts[3], |
|
586 | 31 | $packageParts[4] |
|
587 | ); |
||
588 | } |
||
589 | |||
590 | 31 | return $packages; |
|
591 | } |
||
592 | |||
593 | 11 | private function installPackage($installPath, $packageName, $env) |
|
594 | { |
||
595 | 11 | $env = PuliPackage::ENV_DEV === $env ? ' --dev' : ''; |
|
596 | |||
597 | 11 | $this->puliRunner->run('package --install %path% %package_name% --installer %installer%'.$env, array( |
|
598 | 11 | 'path' => $installPath, |
|
599 | 11 | 'package_name' => $packageName, |
|
600 | 11 | 'installer' => self::INSTALLER_NAME, |
|
601 | )); |
||
602 | 8 | } |
|
603 | |||
604 | 7 | private function removePackage($packageName) |
|
605 | { |
||
606 | 7 | $this->puliRunner->run('package --delete %package_name%', array( |
|
607 | 7 | 'package_name' => $packageName, |
|
608 | )); |
||
609 | 5 | } |
|
610 | |||
611 | 31 | private function removePuliDir() |
|
612 | { |
||
613 | 31 | $relativePuliDir = rtrim($this->getConfigKey('puli-dir'), '/'); |
|
614 | |||
615 | 31 | $puliDir = Path::makeAbsolute($relativePuliDir, $this->rootDir); |
|
616 | |||
617 | // Only remove existing sub-directories of the root directory |
||
618 | 31 | if (!file_exists($puliDir) || 0 !== strpos($puliDir, $this->rootDir.'/')) { |
|
619 | 30 | return; |
|
620 | } |
||
621 | |||
622 | 1 | $this->io->write(sprintf('<info>Deleting the "%s" directory</info>', $relativePuliDir)); |
|
623 | |||
624 | // Remove the .puli directory to prevent upgrade problems |
||
625 | 1 | $filesystem = new Filesystem(); |
|
626 | 1 | $filesystem->remove($puliDir); |
|
627 | 1 | } |
|
628 | |||
629 | 31 | private function buildPuli() |
|
630 | { |
||
631 | 31 | $this->io->write('<info>Running "puli build"</info>'); |
|
632 | |||
633 | 31 | $this->puliRunner->run('build'); |
|
634 | 31 | } |
|
635 | |||
636 | 2 | private function renamePackage($name, $newName) |
|
637 | { |
||
638 | 2 | $this->puliRunner->run('package --rename %old_name% %new_name%', array( |
|
639 | 2 | 'old_name' => $name, |
|
640 | 2 | 'new_name' => $newName, |
|
641 | )); |
||
642 | 1 | } |
|
643 | |||
644 | /** |
||
645 | * @param $message |
||
646 | * @param Exception|null $exception |
||
647 | */ |
||
648 | 12 | private function printWarning($message, Exception $exception = null) |
|
649 | { |
||
650 | 12 | if (!$exception) { |
|
651 | 3 | $reasonPhrase = ''; |
|
652 | 10 | } elseif ($this->io->isVerbose()) { |
|
653 | $reasonPhrase = $exception instanceof PuliRunnerException |
||
654 | ? $exception->getFullError() |
||
655 | : $exception->getMessage()."\n\n".$exception->getTraceAsString(); |
||
656 | } else { |
||
657 | 10 | $reasonPhrase = $exception instanceof PuliRunnerException |
|
658 | 8 | ? $exception->getShortError() |
|
659 | 10 | : $exception->getMessage(); |
|
660 | } |
||
661 | |||
662 | 12 | $this->io->writeError(sprintf( |
|
663 | 12 | '<warning>Warning: %s%s</warning>', |
|
664 | $message, |
||
665 | 12 | $reasonPhrase ? ': '.$reasonPhrase : '.' |
|
666 | )); |
||
667 | 12 | } |
|
668 | |||
669 | 7 | private function printPackageWarning($message, $packageName, $installPath, PuliRunnerException $exception = null) |
|
670 | { |
||
671 | 7 | $this->printWarning(sprintf( |
|
672 | $message, |
||
673 | $packageName, |
||
674 | 7 | Path::makeRelative($installPath, $this->rootDir) |
|
675 | ), $exception); |
||
676 | 7 | } |
|
677 | |||
678 | 32 | private function filterProdPackageNames(array $composerPackages, PackageInterface $package, array &$result = array()) |
|
679 | { |
||
680 | // Resolve aliases |
||
681 | 32 | if ($package instanceof AliasPackage) { |
|
682 | 2 | $package = $package->getAliasOf(); |
|
683 | } |
||
684 | |||
685 | // Package was processed already |
||
686 | 32 | if (isset($result[$package->getName()])) { |
|
687 | return $result; |
||
688 | } |
||
689 | |||
690 | 32 | $result[$package->getName()] = true; |
|
691 | |||
692 | // Recursively filter package names |
||
693 | 32 | foreach ($package->getRequires() as $packageName => $link) { |
|
694 | 21 | if (isset($composerPackages[$packageName])) { |
|
695 | 21 | $this->filterProdPackageNames($composerPackages, $composerPackages[$packageName], $result); |
|
696 | } |
||
697 | } |
||
698 | |||
699 | 32 | return $result; |
|
700 | } |
||
701 | |||
702 | 42 | private function verifyPuliVersion() |
|
703 | { |
||
704 | 42 | $versionString = $this->puliRunner->run('-V'); |
|
705 | |||
706 | 42 | if (!preg_match('~^Puli version (\S+)$~', $versionString, $matches)) { |
|
707 | throw new RuntimeException(sprintf( |
||
708 | 'Could not determine Puli version. "puli -V" returned: %s', |
||
709 | $versionString |
||
710 | )); |
||
711 | } |
||
712 | |||
713 | // the development build of the plugin is always considered compatible |
||
714 | // with the development build of the CLI |
||
715 | // Split strings to prevent replacement during release |
||
716 | 42 | if ('@package_'.'version@' === self::VERSION && '@package_'.'version@' === $matches[1]) { |
|
717 | 1 | return; |
|
718 | } |
||
719 | |||
720 | 41 | View Code Duplication | if (version_compare($matches[1], self::MIN_CLI_VERSION, '<')) { |
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
721 | 1 | throw new RuntimeException(sprintf( |
|
722 | 'Found an unsupported version of the Puli CLI: %s. Please '. |
||
723 | 'upgrade to version %s or higher. You can also install the '. |
||
724 | 1 | 'puli/cli dependency at version %s in your project.', |
|
725 | 1 | $matches[1], |
|
726 | 1 | self::MIN_CLI_VERSION, |
|
727 | 1 | self::MIN_CLI_VERSION |
|
728 | )); |
||
729 | } |
||
730 | |||
731 | 40 | View Code Duplication | if (version_compare($matches[1], self::MAX_CLI_VERSION, '>')) { |
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
732 | 1 | throw new RuntimeException(sprintf( |
|
733 | 'Found an unsupported version of the Puli CLI: %s. Please '. |
||
734 | 'downgrade to a lower version than %s. You can also install '. |
||
735 | 1 | 'the puli/cli dependency in your project.', |
|
736 | 1 | $matches[1], |
|
737 | 1 | self::MAX_CLI_VERSION |
|
738 | )); |
||
739 | } |
||
740 | 39 | } |
|
741 | } |
||
742 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.