Completed
Pull Request — master (#58)
by Marco
03:29
created

FallbackVersions::getVersion()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
crap 2
1
<?php
2
3
namespace PackageVersions;
4
5
/**
6
 * @internal
7
 *
8
 * This is a fallback for {@see \PackageVersions\Versions::getVersion()}
9
 * Do not use this class directly: it is intended to be only used when
10
 * {@see \PackageVersions\Versions} fails to be generated, which typically
11
 * happens when running composer with `--no-scripts` flag)
12
 */
13
final class FallbackVersions
14
{
15
    const ROOT_PACKAGE_NAME = 'unknown/root-package@UNKNOWN';
16
17
    private function __construct()
18
    {
19
    }
20
21
    /**
22
     * @param string $packageName
23
     *
24
     * @return string
25
     *
26
     * @throws \OutOfBoundsException if a version cannot be located
27
     * @throws \UnexpectedValueException if the composer.lock file could not be located
28
     */
29 3
    public static function getVersion(string $packageName) : string
30
    {
31 3
        $versions = iterator_to_array(self::getVersions(self::getComposerLockPath()));
32
33 2
        if (! array_key_exists($packageName, $versions)) {
34 1
            throw new \OutOfBoundsException(
35 1
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
36
            );
37
        }
38
39 1
        return $versions[$packageName];
40
    }
41
42
    /**
43
     * @return string
44
     *
45
     * @throws \UnexpectedValueException
46
     */
47 3
    private static function getComposerLockPath() : string
48
    {
49
        // bold assumption, but there's not here to fix everyone's problems.
50 3
        $checkedPaths = [__DIR__ . '/../../../../../composer.lock', __DIR__ . '/../../composer.lock'];
51
52 3
        foreach ($checkedPaths as $path) {
53 3
            if (file_exists($path)) {
54 3
                return $path;
55
            }
56
        }
57
58 1
        throw new \UnexpectedValueException(sprintf(
59
            'PackageVersions could not locate your `composer.lock` location. This is assumed to be in %s. '
60
            . 'If you customized your composer vendor directory and ran composer installation with --no-scripts, '
61 1
            . 'then you are on your own, and we can\'t really help you. Fix your shit and cut the tooling some slack.',
62 1
            json_encode($checkedPaths)
63
        ));
64
    }
65
66 2
    private static function getVersions(string $composerLockFile) : \Generator
67
    {
68 2
        $lockData = json_decode(file_get_contents($composerLockFile), true);
69
70 2
        $lockData['packages-dev'] = $lockData['packages-dev'] ?? [];
71
72 2
        foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) {
73 2
            yield $package['name'] => $package['version'] . '@' . (
74 2
                $package['source']['reference']?? $package['dist']['reference'] ?? ''
75
            );
76
        }
77
78 2
        yield self::ROOT_PACKAGE_NAME;
79 2
    }
80
}
81