Passed
Pull Request — master (#76)
by Théo
02:23
created

ComposerConfiguration::retrieveDevPackages()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
eloc 10
nc 2
nop 1
cc 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace KevinGH\Box\Composer;
6
7
use function array_map;
8
use Assert\Assertion;
9
use const DIRECTORY_SEPARATOR;
10
use function dirname;
11
use function file_exists;
12
use function KevinGH\Box\FileSystem\canonicalize;
13
use function KevinGH\Box\FileSystem\file_contents;
14
use function KevinGH\Box\FileSystem\make_path_absolute;
15
use function KevinGH\Box\FileSystem\make_path_relative;
16
use KevinGH\Box\Json\Json;
17
use function realpath;
18
19
final class ComposerConfiguration
20
{
21
    /**
22
     * Attempts to locate the `composer.json` and `composer.lock` files in the provided base-path in order to collect
23
     * all the dev packages.
24
     *
25
     * @param string $basePath
26
     *
27
     * @return string[] Dev package paths
28
     */
29
    public static function retrieveDevPackages(string $basePath): array
30
    {
31
        Assertion::directory($basePath);
32
33
        $composerFile = make_path_absolute('composer.json', $basePath);
34
        $composerLockFile = make_path_absolute('composer.lock', $basePath);
35
36
        if (file_exists($composerFile)) {
37
            Assertion::file($composerFile, 'Expected "%s" to be a file. Directory or link found.');
38
            Assertion::file($composerLockFile, 'Expected "%s" to exists. The file is either missing or a ditectory/link has been found instead.');
39
40
            $composerFileContents = file_contents($composerFile);
41
            $composerLockFileContents = file_contents($composerLockFile);
42
43
            return self::getDevPackagePaths($basePath, $composerFileContents, $composerLockFileContents);
44
        }
45
46
        return [];
47
    }
48
49
    /**
50
     * @param string $basePath
51
     * @param string $composerFileContents
52
     * @param string $composerLockFileContents
53
     *
54
     * @return string[] Dev packages paths
55
     */
56
    private static function getDevPackagePaths(
57
        string $basePath,
58
        string $composerFileContents,
59
        string $composerLockFileContents
60
    ): array
61
    {
62
        $vendorDir = make_path_absolute(
63
            self::getVendorDir($composerFileContents),
64
            $basePath
65
        );
66
67
        $packageNames = self::getDevPackageNames($composerLockFileContents);
68
69
        return array_map(
70
            function (string $packageName) use ($vendorDir): string {
71
                return realpath($vendorDir.DIRECTORY_SEPARATOR.$packageName);
72
            },
73
            $packageNames
74
        );
75
    }
76
77
    private static function getVendorDir(string $composerFileContents): string
78
    {
79
        $config = (new Json())->decode($composerFileContents, true);
80
81
        if (!array_key_exists('config', $config)) {
0 ignored issues
show
Bug introduced by
It seems like $config can also be of type stdClass; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

81
        if (!array_key_exists('config', /** @scrutinizer ignore-type */ $config)) {
Loading history...
82
            return 'vendor';
83
        }
84
85
        if (!array_key_exists('vendor-dir', $config['config'])) {
86
            return 'vendor';
87
        }
88
89
        return $config['config']['vendor-dir'];
90
    }
91
92
    /**
93
     * @param string $composerLockFileContents
94
     *
95
     * @return string[] Names of the dev packages
96
     */
97
    private static function getDevPackageNames(string $composerLockFileContents): array
98
    {
99
        $config = (new Json())->decode($composerLockFileContents, true);
100
101
        if (!array_key_exists('packages-dev', $config)) {
0 ignored issues
show
Bug introduced by
It seems like $config can also be of type stdClass; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        if (!array_key_exists('packages-dev', /** @scrutinizer ignore-type */ $config)) {
Loading history...
102
            return [];
103
        }
104
105
        return array_map(
106
            function (array $package): string {
107
                return $package['name'];
108
            },
109
            $config['packages-dev']
110
        );
111
    }
112
}