Completed
Push — master ( e799c5...08fb5f )
by Marco
25s
created

FallbackVersions::getPackageData()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 40
ccs 15
cts 15
cp 1
rs 8.6577
c 0
b 0
f 0
cc 6
nc 10
nop 0
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PackageVersions;
6
7
use Generator;
8
use OutOfBoundsException;
9
use UnexpectedValueException;
10
use function array_key_exists;
11
use function array_merge;
12
use function file_exists;
13
use function file_get_contents;
14
use function getcwd;
15
use function iterator_to_array;
16
use function json_decode;
17
use function json_encode;
18
use function sprintf;
19
20
/**
21
 * @internal
22
 *
23
 * This is a fallback for {@see \PackageVersions\Versions::getVersion()}
24
 * Do not use this class directly: it is intended to be only used when
25
 * {@see \PackageVersions\Versions} fails to be generated, which typically
26
 * happens when running composer with `--no-scripts` flag)
27
 */
28
final class FallbackVersions
29
{
30
    public const ROOT_PACKAGE_NAME = 'unknown/root-package@UNKNOWN';
31
32
    private function __construct()
33
    {
34
    }
35
36
    /**
37
     * @throws OutOfBoundsException If a version cannot be located.
38
     * @throws UnexpectedValueException If the composer.lock file could not be located.
39 3
     */
40
    public static function getVersion(string $packageName) : string
41 3
    {
42
        $versions = iterator_to_array(self::getVersions(self::getPackageData()));
43 2
44 1
        if (! array_key_exists($packageName, $versions)) {
45 1
            throw new OutOfBoundsException(
46
                'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files'
47
            );
48
        }
49 1
50
        return $versions[$packageName];
51
    }
52
53
    /**
54
     * @throws UnexpectedValueException
55 3
     */
56
    private static function getPackageData() : array
57
    {
58 3
        $checkedPaths = [
59
            // The top-level project's ./vendor/composer/installed.json
60 3
            getcwd() . '/vendor/composer/installed.json',
61 3
            // The top-level project's ./composer.lock
62 3
            getcwd() . '/composer.lock',
63
            // This package's composer.lock
64
            __DIR__ . '/../../composer.lock',
65
        ];
66 1
67
        $packageData = [];
68
        foreach ($checkedPaths as $path) {
69 1
            if (file_exists($path)) {
70 1
                $data = json_decode(file_get_contents($path), true);
71
                switch (basename($path)) {
72
                    case 'installed.json':
73
                        $packageData[] = $data;
74 2
                        break;
75
                    case 'composer.lock':
76 2
                        $packageData[] = $data['packages'] + ($data['packages-dev'] ?? []);
77
                        break;
78 2
                    default:
0 ignored issues
show
Coding Style introduced by
DEFAULT statements must be defined using a colon

As per the PSR-2 coding standard, default statements should not be wrapped in curly braces.

switch ($expr) {
    default: { //wrong
        doSomething();
        break;
    }
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
79
                        // intentionally left blank
80 2
                }
81 2
            }
82 2
        }
83
84
        if ($packageData !== []) {
85
            return array_merge(...$packageData);
86 2
        }
87 2
88
        throw new UnexpectedValueException(sprintf(
89
            'PackageVersions could not locate the `vendor/composer/installed.json` or your `composer.lock` '
90
            . 'location. This is assumed to be in %s. If you customized your composer vendor directory and ran composer '
91
            . 'installation with --no-scripts or if you deployed without the required composer files, then you are on '
92
            . 'your own, and we can\'t really help you. Fix your shit and cut the tooling some slack.',
93
            json_encode($checkedPaths)
94
        ));
95
    }
96
97
    private static function getVersions(array $packageData) : Generator
98
    {
99
        foreach ($packageData as $package) {
100
            yield $package['name'] => $package['version'] . '@' . (
101
                $package['source']['reference'] ?? $package['dist']['reference'] ?? ''
102
            );
103
        }
104
105
        yield self::ROOT_PACKAGE_NAME;
106
    }
107
}
108