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

FallbackVersions   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 68
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 91.67%

Importance

Changes 0
Metric Value
wmc 8
lcom 0
cbo 0
dl 0
loc 68
ccs 22
cts 24
cp 0.9167
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getComposerLockPath() 0 18 3
A getVersion() 0 12 2
A getVersions() 0 14 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