Completed
Pull Request — master (#82)
by
unknown
25:00
created

FallbackVersions::getPackageData()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 15
cts 15
cp 1
rs 9.0808
c 0
b 0
f 0
cc 5
nc 5
nop 0
crap 5
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 32 and the first side effect is on line 28.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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
0 ignored issues
show
Bug introduced by
Possible parse error: class missing opening or closing brace
Loading history...
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
        foreach ($checkedPaths as $path) {
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
68
            if (file_exists($path)) {
69 1
                switch (basename($path)) {
70 1
                    case 'installed.json':
71
                        return json_decode(file_get_contents($path), true);
72
                    case 'composer.lock':
73
                        $data = json_decode(file_get_contents($path), true);
74 2
                        return array_merge($data['packages'], $data['packages-dev'] ?? []);
75
                    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...
76 2
                        // intentionally left blank
77
                }
78 2
            }
79
        }
80 2
81 2
        throw new UnexpectedValueException(sprintf(
82 2
            'PackageVersions could not locate the `vendor/composer/installed.json` or your `composer.lock` '
83
            . 'location. This is assumed to be in %s. If you customized your composer vendor directory and ran composer '
84
            . 'installation with --no-scripts or if you deployed without the required composer files, then you are on '
85
            . 'your own, and we can\'t really help you. Fix your shit and cut the tooling some slack.',
86 2
            json_encode($checkedPaths)
87 2
        ));
88
    }
0 ignored issues
show
Coding Style introduced by
Closing brace indented incorrectly; expected 16 spaces, found 4
Loading history...
89
90
    private static function getVersions(array $packageData) : Generator
91
    {
92
        foreach ($packageData as $package) {
93
            yield $package['name'] => $package['version'] . '@' . (
94
                $package['source']['reference'] ?? $package['dist']['reference'] ?? ''
95
            );
96
        }
97
98
        yield self::ROOT_PACKAGE_NAME;
99
    }
100
}
0 ignored issues
show
Coding Style introduced by
Closing brace indented incorrectly; expected 12 spaces, found 0
Loading history...
101