Completed
Pull Request — master (#46)
by Chris
04:14
created

PuliPluginImpl::preAutoloadDump()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 35
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5.2331

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 35
ccs 15
cts 19
cp 0.7895
rs 8.439
cc 5
eloc 19
nc 10
nop 0
crap 5.2331
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 41
    public function __construct(Event $event, PuliRunner $puliRunner = null)
112
    {
113 41
        $this->composer = $event->getComposer();
114 41
        $this->io = $event->getIO();
115 41
        $this->config = $this->composer->getConfig();
116 41
        $this->isDev = $event->isDevMode();
117 41
        $this->puliRunner = $puliRunner;
118 41
        $this->rootDir = Path::normalize(getcwd());
119
120 41
        $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 41
        $vendorDir = Path::makeAbsolute($vendorDir, $this->rootDir);
125
126 41
        $this->autoloadFile = $vendorDir.'/autoload.php';
127 41
    }
128
129 2
    public function preAutoloadDump()
130
    {
131 2
        if (!$this->initialized) {
132 2
            $this->initialize();
133
        }
134
135
        // This method is called twice. Run it only once.
136 2
        if (!$this->runPreAutoloadDump) {
137
            return;
138
        }
139
140 2
        $this->runPreAutoloadDump = false;
141
142
        try {
143 2
            $factoryClass = $this->getConfigKey('factory.in.class');
144 2
            $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 2
        $factoryFile = Path::makeAbsolute($factoryFile, $this->rootDir);
0 ignored issues
show
Bug introduced by
It seems like $factoryFile can also be of type boolean or null; however, Webmozart\PathUtil\Path::makeAbsolute() does only seem to accept string, maybe add an additional type check?

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:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
152
153 2
        $autoload = $this->composer->getPackage()->getAutoload();
154 2
        $autoload['classmap'][] = $factoryFile;
155
156 2
        $this->composer->getPackage()->setAutoload($autoload);
157
158 2
        if (!file_exists($factoryFile)) {
159 1
            $filesystem = new Filesystem();
160
            // Let Composer find the factory class with a temporary stub
161 1
            $filesystem->dumpFile($factoryFile, '<?php class '.$factoryClass.' {}');
162
        }
163 2
    }
164
165 5
    public function postAutoloadDump()
166
    {
167 5
        if (!$this->initialized) {
168 5
            $this->initialize();
169
        }
170
171
        // This method is called twice. Run it only once.
172 5
        if (!$this->runPostAutoloadDump) {
173 1
            return;
174
        }
175
176 5
        $this->runPostAutoloadDump = false;
177
178
        try {
179 5
            $factoryClass = $this->getConfigKey('factory.in.class');
180 1
        } catch (PuliRunnerException $e) {
181 1
            $this->printWarning('Could not load Puli configuration', $e);
182
183 1
            return;
184
        }
185
186 4
        $this->insertFactoryClassConstant($this->autoloadFile, $factoryClass);
187 4
        $this->setBootstrapFile($this->autoloadFile);
188 4
    }
189
190
    /**
191
     * Updates the Puli repository after Composer installations/updates.
192
     */
193 34
    public function postInstall()
194
    {
195 34
        if (!$this->initialized) {
196 34
            $this->initialize();
197
        }
198
199
        // This method is called twice. Run it only once.
200 34
        if (!$this->runPostInstall) {
201 3
            return;
202
        }
203
204 32
        $this->runPostInstall = false;
205
206 32
        $this->io->write('<info>Synchronizing Puli with Composer</info>');
207
208 32
        $rootPackage = $this->composer->getPackage();
209 32
        $composerPackages = $this->loadComposerPackages();
210 32
        $prodPackageNames = $this->filterProdPackageNames($composerPackages, $rootPackage);
211 32
        $env = $this->isDev ? PuliPackage::ENV_DEV : PuliPackage::ENV_PROD;
212
213
        try {
214 32
            $puliPackages = $this->loadPuliPackages();
215 1
        } catch (PuliRunnerException $e) {
216 1
            $this->printWarning('Could not load Puli packages', $e);
217
218 1
            return;
219
        }
220
221
        // Don't remove non-existing packages in production environment
222
        // Removed packages could be dev dependencies (i.e. "require-dev"
223
        // of the root package or "require" of another dev dependency), and
224
        // we can't find out whether they are since Composer doesn't load them
225 31
        if (PuliPackage::ENV_PROD !== $env) {
226 3
            $this->removeRemovedPackages($composerPackages, $puliPackages);
227
        }
228
229 31
        $this->installNewPackages($composerPackages, $prodPackageNames, $puliPackages);
230
231
        // Don't print warnings for non-existing packages in production
232 31
        if (PuliPackage::ENV_PROD !== $env) {
233 3
            $this->checkForNotFoundErrors($puliPackages);
234
        }
235
236 31
        $this->checkForNotLoadableErrors($puliPackages);
237 31
        $this->adoptComposerName($puliPackages);
238 31
        $this->removePuliDir();
239 31
        $this->buildPuli();
240 31
    }
241
242 41
    private function initialize()
243
    {
244 41
        if (!file_exists($this->autoloadFile)) {
245
            $filesystem = new Filesystem();
246
            // Avoid problems if using the runner before autoload.php has been
247
            // generated
248
            $filesystem->dumpFile($this->autoloadFile, '');
249
        }
250
251 41
        $this->initialized = true;
252
253
        // Keep the manually set runner
254 41
        if (null === $this->puliRunner) {
255
            try {
256
                // Add Composer's bin directory in case the "puli" executable is
257
                // installed with Composer
258
                $this->puliRunner = new PuliRunner($this->config->get('bin-dir'));
259
            } catch (RuntimeException $e) {
260
                $this->printWarning('Plugin initialization failed', $e);
261
                $this->runPreAutoloadDump = false;
262
                $this->runPostAutoloadDump = false;
263
                $this->runPostInstall = false;
264
            }
265
        }
266
267
        // Use the runner to verify if Puli has the right version
268
        try {
269 41
            $this->verifyPuliVersion();
270 2
        } catch (RuntimeException $e) {
271 2
            $this->printWarning('Version check failed', $e);
272 2
            $this->runPreAutoloadDump = false;
273 2
            $this->runPostAutoloadDump = false;
274 2
            $this->runPostInstall = false;
275
        }
276 41
    }
277
278
    /**
279
     * @param PackageInterface[] $composerPackages
280
     * @param bool[]             $prodPackageNames
281
     * @param PuliPackage[]      $puliPackages
282
     */
283 31
    private function installNewPackages(array $composerPackages, array $prodPackageNames, array &$puliPackages)
284
    {
285 31
        $installationManager = $this->composer->getInstallationManager();
286
287 31
        foreach ($composerPackages as $packageName => $package) {
288 21
            if ($package instanceof AliasPackage) {
289 2
                $package = $package->getAliasOf();
290
            }
291
292
            // We need to normalize the system-dependent paths returned by Composer
293 21
            $installPath = Path::normalize($installationManager->getInstallPath($package));
294 21
            $env = isset($prodPackageNames[$packageName]) ? PuliPackage::ENV_PROD : PuliPackage::ENV_DEV;
295
296
            // Skip meta packages
297 21
            if ('' === $installPath) {
298 1
                continue;
299
            }
300
301 20
            if (isset($puliPackages[$packageName])) {
302 15
                $puliPackage = $puliPackages[$packageName];
303
304
                // Only proceed if the install path or environment has changed
305 15
                if ($installPath === $puliPackage->getInstallPath() && $env === $puliPackage->getEnvironment()) {
306 14
                    continue;
307
                }
308
309
                // Only remove packages installed by Composer
310 6
                if (self::INSTALLER_NAME === $puliPackage->getInstallerName()) {
311 5
                    $this->io->write(sprintf(
312 5
                        'Reinstalling <info>%s</info> (<comment>%s</comment>) in <comment>%s</comment>',
313
                        $packageName,
314 5
                        Path::makeRelative($installPath, $this->rootDir),
315
                        $env
316
                    ));
317
318
                    try {
319 5
                        $this->removePackage($packageName);
320 1
                    } catch (PuliRunnerException $e) {
321 1
                        $this->printPackageWarning('Could not remove package "%s" (at "%s")', $packageName, $installPath, $e);
322
323 6
                        continue;
324
                    }
325
                }
326
            } else {
327 6
                $this->io->write(sprintf(
328 6
                    'Installing <info>%s</info> (<comment>%s</comment>) in <comment>%s</comment>',
329
                    $packageName,
330 6
                    Path::makeRelative($installPath, $this->rootDir),
331
                    $env
332
                ));
333
            }
334
335
            try {
336 11
                $this->installPackage($installPath, $packageName, $env);
337 3
            } catch (PuliRunnerException $e) {
338 3
                $this->printPackageWarning('Could not install package "%s" (at "%s")', $packageName, $installPath, $e);
339
340 3
                continue;
341
            }
342
343 8
            $puliPackages[$packageName] = new PuliPackage(
344
                $packageName,
345 8
                self::INSTALLER_NAME,
346
                $installPath,
347 8
                PuliPackage::STATE_ENABLED,
348
                $env
349
            );
350
        }
351 31
    }
352
353
    /**
354
     * @param PackageInterface[] $composerPackages
355
     * @param PuliPackage[]      $puliPackages
356
     */
357 3
    private function removeRemovedPackages(array $composerPackages, array &$puliPackages)
358
    {
359
        /** @var PuliPackage[] $notFoundPackages */
360
        $notFoundPackages = array_filter($puliPackages, function (PuliPackage $package) {
361 3
            return PuliPackage::STATE_NOT_FOUND === $package->getState()
362 3
                && PuliPluginImpl::INSTALLER_NAME === $package->getInstallerName();
363 3
        });
364
365 3
        foreach ($notFoundPackages as $packageName => $package) {
366
            // Check whether package was only moved
367 3
            if (isset($composerPackages[$packageName])) {
368 1
                continue;
369
            }
370
371 2
            $this->io->write(sprintf(
372 2
                'Removing <info>%s</info> (<comment>%s</comment>)',
373
                $packageName,
374 2
                Path::makeRelative($package->getInstallPath(), $this->rootDir)
375
            ));
376
377
            try {
378 2
                $this->removePackage($packageName);
379 1
            } catch (PuliRunnerException $e) {
380 1
                $this->printPackageWarning('Could not remove package "%s" (at "%s")', $packageName, $package->getInstallPath(), $e);
381
382 1
                continue;
383
            }
384
385 1
            unset($puliPackages[$packageName]);
386
        }
387 3
    }
388
389 3 View Code Duplication
    private function checkForNotFoundErrors(array $puliPackages)
0 ignored issues
show
Duplication introduced by
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.

Loading history...
390
    {
391
        /** @var PuliPackage[] $notFoundPackages */
392 3
        $notFoundPackages = array_filter($puliPackages,
393
            function (PuliPackage $package) {
394 3
                return PuliPackage::STATE_NOT_FOUND === $package->getState()
395 3
                && PuliPluginImpl::INSTALLER_NAME === $package->getInstallerName();
396 3
            });
397
398 3
        foreach ($notFoundPackages as $package) {
399 2
            $this->printPackageWarning(
400 2
                'The package "%s" (at "%s") could not be found',
401 2
                $package->getName(),
402 2
                $package->getInstallPath()
403
            );
404
        }
405 3
    }
406
407 31 View Code Duplication
    private function checkForNotLoadableErrors(array $puliPackages)
0 ignored issues
show
Duplication introduced by
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.

Loading history...
408
    {
409
        /** @var PuliPackage[] $notLoadablePackages */
410
        $notLoadablePackages = array_filter($puliPackages, function (PuliPackage $package) {
411 31
            return PuliPackage::STATE_NOT_LOADABLE === $package->getState()
412 31
                && PuliPluginImpl::INSTALLER_NAME === $package->getInstallerName();
413 31
        });
414
415 31
        foreach ($notLoadablePackages as $package) {
416 1
            $this->printPackageWarning(
417 1
                'The package "%s" (at "%s") could not be loaded',
418 1
                $package->getName(),
419 1
                $package->getInstallPath()
420
            );
421
        }
422 31
    }
423
424 31
    private function adoptComposerName(array $puliPackages)
425
    {
426 31
        $rootDir = $this->rootDir;
427
428
        /** @var PuliPackage[] $rootPackages */
429 31
        $rootPackages = array_filter($puliPackages, function (PuliPackage $package) use ($rootDir) {
430 31
            return !$package->getInstallerName() && $rootDir === $package->getInstallPath();
431 31
        });
432
433 31
        if (0 === count($rootPackages)) {
434
            // This should never happen
435
            $this->printWarning('No root package could be found');
436
437
            return;
438
        }
439
440 31
        if (count($rootPackages) > 1) {
441
            // This should never happen
442
            $this->printWarning('More than one root package was found');
443
444
            return;
445
        }
446
447
        /** @var PuliPackage $rootPackage */
448 31
        $rootPackage = reset($rootPackages);
449 31
        $name = $rootPackage->getName();
450 31
        $newName = $this->composer->getPackage()->getName();
451
452
        // Rename the root package after changing the name in composer.json
453 31
        if ($name !== $newName) {
454
            try {
455 2
                $this->renamePackage($name, $newName);
456 1
            } catch (PuliRunnerException $e) {
457 1
                $this->printWarning(sprintf(
458 1
                    'Could not rename root package to "%s"',
459
                    $newName
460
                ), $e);
461
            }
462
        }
463 31
    }
464
465 4
    private function insertFactoryClassConstant($autoloadFile, $factoryClass)
466
    {
467 4
        if (!file_exists($autoloadFile)) {
468
            throw new PuliPluginException(sprintf(
469
                'Could not adjust autoloader: The file %s was not found.',
470
                $autoloadFile
471
            ));
472
        }
473
474 4
        $this->io->write('<info>Generating the "PULI_FACTORY_CLASS" constant</info>');
475
476 4
        $contents = file_get_contents($autoloadFile);
477 4
        $escFactoryClass = var_export($factoryClass, true);
478 4
        $constant = "if (!defined('PULI_FACTORY_CLASS')) {\n";
479 4
        $constant .= sprintf("    define('PULI_FACTORY_CLASS', %s);\n", $escFactoryClass);
480 4
        $constant .= "}\n\n";
481
482
        // Regex modifiers:
483
        // "m": \s matches newlines
484
        // "D": $ matches at EOF only
485
        // Translation: insert before the last "return" in the file
486 4
        $contents = preg_replace('/\n(?=return [^;]+;\s*$)/mD', "\n".$constant,
487
            $contents);
488
489 4
        file_put_contents($autoloadFile, $contents);
490 4
    }
491
492 4
    private function setBootstrapFile($autoloadFile)
493
    {
494 4
        $bootstrapFile = $this->getConfigKey('bootstrap-file');
495
496
        // Don't change user-defined bootstrap files
497 4
        if (!empty($bootstrapFile)) {
498 1
            return;
499
        }
500
501 3
        $relAutoloadFile = Path::makeRelative($autoloadFile, $this->rootDir);
502
503 3
        $this->io->write(sprintf('<info>Setting "bootstrap-file" to "%s"</info>', $relAutoloadFile));
504
505 3
        $this->setConfigKey('bootstrap-file', $relAutoloadFile);
506 3
    }
507
508
    /**
509
     * Loads Composer's currently installed packages.
510
     *
511
     * @return PackageInterface[] The installed packages indexed by their names.
512
     */
513 32
    private function loadComposerPackages()
514
    {
515 32
        $repository = $this->composer->getRepositoryManager()->getLocalRepository();
516 32
        $packages = array();
517
518 32
        foreach ($repository->getPackages() as $package) {
519
            /* @var PackageInterface $package */
520 21
            $packages[$package->getName()] = $package;
521
        }
522
523 32
        return $packages;
524
    }
525
526 38
    private function getConfigKey($key)
527
    {
528 38
        $value = trim($this->puliRunner->run('config %key% --parsed', array(
529 38
            'key' => $key,
530
        )));
531
532
        switch ($value) {
533 37
            case 'null':
534 1
                return null;
535 37
            case 'true':
536
                return true;
537 37
            case 'false':
538
                return false;
539
            default:
540 37
                return $value;
541
        }
542
    }
543
544 3
    private function setConfigKey($key, $value)
545
    {
546 3
        $this->puliRunner->run('config %key% %value%', array(
547 3
            'key' => $key,
548 3
            'value' => $value,
549
        ));
550 3
    }
551
552
    /**
553
     * @return PuliPackage[]
554
     */
555 32
    private function loadPuliPackages()
556
    {
557 32
        $packages = array();
558
559 32
        $output = $this->puliRunner->run('package --list --format %format%', array(
560 32
            'format' => '%name%;%installer%;%install_path%;%state%;%env%',
561
        ));
562
563
        // PuliRunner replaces \r\n by \n for those Windows boxes
564 31
        foreach (explode("\n", $output) as $packageLine) {
565 31
            if (!$packageLine) {
566 31
                continue;
567
            }
568
569 31
            $packageParts = explode(';', $packageLine);
570
571 31
            $packages[$packageParts[0]] = new PuliPackage(
572 31
                $packageParts[0],
573 31
                $packageParts[1],
574 31
                $packageParts[2],
575 31
                $packageParts[3],
576 31
                $packageParts[4]
577
            );
578
        }
579
580 31
        return $packages;
581
    }
582
583 11
    private function installPackage($installPath, $packageName, $env)
584
    {
585 11
        $env = PuliPackage::ENV_DEV === $env ? ' --dev' : '';
586
587 11
        $this->puliRunner->run('package --install %path% %package_name% --installer %installer%'.$env, array(
588 11
            'path' => $installPath,
589 11
            'package_name' => $packageName,
590 11
            'installer' => self::INSTALLER_NAME,
591
        ));
592 8
    }
593
594 7
    private function removePackage($packageName)
595
    {
596 7
        $this->puliRunner->run('package --delete %package_name%', array(
597 7
            'package_name' => $packageName,
598
        ));
599 5
    }
600
601 31
    private function removePuliDir()
602
    {
603 31
        $relativePuliDir = rtrim($this->getConfigKey('puli-dir'), '/');
604
605 31
        $puliDir = Path::makeAbsolute($relativePuliDir, $this->rootDir);
606
607
        // Only remove existing sub-directories of the root directory
608 31
        if (!file_exists($puliDir) || 0 !== strpos($puliDir, $this->rootDir.'/')) {
609 30
            return;
610
        }
611
612 1
        $this->io->write(sprintf('<info>Deleting the "%s" directory</info>', $relativePuliDir));
613
614
        // Remove the .puli directory to prevent upgrade problems
615 1
        $filesystem = new Filesystem();
616 1
        $filesystem->remove($puliDir);
617 1
    }
618
619 31
    private function buildPuli()
620
    {
621 31
        $this->io->write('<info>Running "puli build"</info>');
622
623 31
        $this->puliRunner->run('build');
624 31
    }
625
626 2
    private function renamePackage($name, $newName)
627
    {
628 2
        $this->puliRunner->run('package --rename %old_name% %new_name%', array(
629 2
            'old_name' => $name,
630 2
            'new_name' => $newName,
631
        ));
632 1
    }
633
634
    /**
635
     * @param                $message
636
     * @param Exception|null $exception
637
     */
638 12
    private function printWarning($message, Exception $exception = null)
639
    {
640 12
        if (!$exception) {
641 3
            $reasonPhrase = '';
642 10
        } elseif ($this->io->isVerbose()) {
643
            $reasonPhrase = $exception instanceof PuliRunnerException
644
                ? $exception->getFullError()
645
                : $exception->getMessage()."\n\n".$exception->getTraceAsString();
646
        } else {
647 10
            $reasonPhrase = $exception instanceof PuliRunnerException
648 8
                ? $exception->getShortError()
649 10
                : $exception->getMessage();
650
        }
651
652 12
        $this->io->writeError(sprintf(
653 12
            '<warning>Warning: %s%s</warning>',
654
            $message,
655 12
            $reasonPhrase ? ': '.$reasonPhrase : '.'
656
        ));
657 12
    }
658
659 7
    private function printPackageWarning($message, $packageName, $installPath, PuliRunnerException $exception = null)
660
    {
661 7
        $this->printWarning(sprintf(
662
            $message,
663
            $packageName,
664 7
            Path::makeRelative($installPath, $this->rootDir)
665
        ), $exception);
666 7
    }
667
668 32
    private function filterProdPackageNames(array $composerPackages, PackageInterface $package, array &$result = array())
669
    {
670
        // Resolve aliases
671 32
        if ($package instanceof AliasPackage) {
672 2
            $package = $package->getAliasOf();
673
        }
674
675
        // Package was processed already
676 32
        if (isset($result[$package->getName()])) {
677
            return $result;
678
        }
679
680 32
        $result[$package->getName()] = true;
681
682
        // Recursively filter package names
683 32
        foreach ($package->getRequires() as $packageName => $link) {
684 21
            if (isset($composerPackages[$packageName])) {
685 21
                $this->filterProdPackageNames($composerPackages, $composerPackages[$packageName], $result);
686
            }
687
        }
688
689 32
        return $result;
690
    }
691
692 41
    private function verifyPuliVersion()
693
    {
694 41
        $versionString = $this->puliRunner->run('-V');
695
696 41
        if (!preg_match('~^Puli version (\S+)$~', $versionString, $matches)) {
697
            throw new RuntimeException(sprintf(
698
                'Could not determine Puli version. "puli -V" returned: %s',
699
                $versionString
700
            ));
701
        }
702
703
        // the development build of the plugin is always considered compatible
704
        // with the development build of the CLI
705
        // Split strings to prevent replacement during release
706 41
        if ('@package_'.'version@' === self::VERSION && '@package_'.'version@' === $matches[1]) {
707 1
            return;
708
        }
709
710 40 View Code Duplication
        if (version_compare($matches[1], self::MIN_CLI_VERSION, '<')) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
711 1
            throw new RuntimeException(sprintf(
712
                'Found an unsupported version of the Puli CLI: %s. Please '.
713
                'upgrade to version %s or higher. You can also install the '.
714 1
                'puli/cli dependency at version %s in your project.',
715 1
                $matches[1],
716 1
                self::MIN_CLI_VERSION,
717 1
                self::MIN_CLI_VERSION
718
            ));
719
        }
720
721 39 View Code Duplication
        if (version_compare($matches[1], self::MAX_CLI_VERSION, '>')) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
722 1
            throw new RuntimeException(sprintf(
723
                'Found an unsupported version of the Puli CLI: %s. Please '.
724
                'downgrade to a lower version than %s. You can also install '.
725 1
                'the puli/cli dependency in your project.',
726 1
                $matches[1],
727 1
                self::MAX_CLI_VERSION
728
            ));
729
        }
730 38
    }
731
}
732