Passed
Pull Request — master (#96)
by Dmitriy
18:07 queued 10s
created

Package::readConfigFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
cc 2
nc 2
nop 0
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Composer\Config;
6
7
use Composer\Package\CompletePackageInterface;
8
use Composer\Package\PackageInterface;
9
use Composer\Package\RootPackageInterface;
10
use Composer\Util\Filesystem;
11
12
/**
13
 * Class Package.
14
 */
15
class Package
16
{
17
    public const EXTRA_FILES_OPTION_NAME = 'config-plugin';
18
    public const EXTRA_DEV_FILES_OPTION_NAME = 'config-plugin-dev';
19
    public const EXTRA_OUTPUT_DIR_OPTION_NAME = 'config-plugin-output-dir';
20
    public const EXTRA_ALTERNATIVES_OPTION_NAME = 'config-plugin-alternatives';
21
22
    public const CONFIG_FILE_NAME_COMPOSER = 'composer.json';
23
    public const CONFIG_FILE_NAME_PLUGIN = '.composer-config-plugin.php';
24
25
    private PackageInterface $package;
26
27
    /**
28
     * @var array composer.json raw data array
29
     */
30
    private array $data;
31
32
    /**
33
     * @var array .composer-config-plugin.php config array
34
     */
35
    private array $config;
36
37
    /**
38
     * @var string absolute path to the root base directory
39
     */
40
    private string $baseDir;
41
42
    /**
43
     * @var string absolute path to vendor directory
44
     */
45
    private string $vendorDir;
46
47
    /**
48
     * @var Filesystem utility
49
     */
50
    private Filesystem $filesystem;
51
52
    public function __construct(PackageInterface $package, string $vendorDir)
53
    {
54
        $this->package = $package;
55
        $this->filesystem = new Filesystem();
56
57
        $this->vendorDir = $this->filesystem->normalizePath($vendorDir);
58
        $this->baseDir = dirname($this->vendorDir);
59
        $this->data = $this->readRawData();
60
        $this->config = $this->readConfigFile();
61
    }
62
63
    /**
64
     * @return string package pretty name, like: vendor/name
65
     */
66
    public function getPrettyName(): string
67
    {
68
        return $this->package->getPrettyName();
69
    }
70
71
    /**
72
     * @return string package version, like: 3.0.16.0, 9999999-dev
73
     */
74
    public function getVersion(): string
75
    {
76
        return $this->package->getVersion();
77
    }
78
79
    /**
80
     * @return string package CVS revision, like: 3a4654ac9655f32888efc82fb7edf0da517d8995
81
     */
82
    public function getSourceReference(): ?string
83
    {
84
        return $this->package->getSourceReference();
85
    }
86
87
    /**
88
     * @return string package dist revision, like: 3a4654ac9655f32888efc82fb7edf0da517d8995
89
     */
90
    public function getDistReference(): ?string
91
    {
92
        return $this->package->getDistReference();
93
    }
94
95
    /**
96
     * @return bool is package complete
97
     */
98
    public function isComplete(): bool
99
    {
100
        return $this->package instanceof CompletePackageInterface;
101
    }
102
103
    /**
104
     * @return bool is this a root package
105
     */
106
    public function isRoot(): bool
107
    {
108
        return $this->package instanceof RootPackageInterface;
109
    }
110
111
    /**
112
     * @return array autoload configuration array
113
     */
114
    public function getAutoload(): array
115
    {
116
        return $this->getRawValue('autoload') ?? $this->package->getAutoload();
117
    }
118
119
    /**
120
     * @return array autoload-dev configuration array
121
     */
122
    public function getDevAutoload(): array
123
    {
124
        return $this->getRawValue('autoload-dev') ?? $this->package->getDevAutoload();
125
    }
126
127
    /**
128
     * @return array require configuration array
129
     */
130
    public function getRequires(): array
131
    {
132
        return $this->getRawValue('require') ?? $this->package->getRequires();
133
    }
134
135
    /**
136
     * @return array require-dev configuration array
137
     */
138
    public function getDevRequires(): array
139
    {
140
        return $this->getRawValue('require-dev') ?? $this->package->getDevRequires();
141
    }
142
143
    /**
144
     * @return array files array
145
     */
146
    public function getFiles(): array
147
    {
148
        return $this->getConfigValue(self::EXTRA_FILES_OPTION_NAME, []);
149
    }
150
151
    /**
152
     * @return array dev-files array
153
     */
154
    public function getDevFiles(): array
155
    {
156
        return $this->getConfigValue(self::EXTRA_DEV_FILES_OPTION_NAME, []);
157
    }
158
159
    /**
160
     * @return mixed alternatives array or path to config
161
     */
162
    public function getAlternatives()
163
    {
164
        return $this->getConfigValue(self::EXTRA_ALTERNATIVES_OPTION_NAME);
165
    }
166
167
    /**
168
     * Get configuration value or default
169
     *
170
     * @param string $key key to look for in .composer-config-plugin.php or extra configuration
171
     * @param mixed $default default to return if there's no .composer-config-plugin.php and extra configuration value
172
     * @return mixed configuration value or default
173
     */
174
    private function getConfigValue(string $key, $default = null)
175
    {
176
        return array_key_exists($key, $this->config) ? $this->config[$key] : $this->getExtraValue($key, $default);
177
    }
178
179
    /**
180
     * Get extra configuration value or default
181
     *
182
     * @param string $key key to look for in extra configuration
183
     * @param mixed $default default to return if there's no extra configuration value
184
     * @return mixed extra configuration value or default
185
     */
186
    private function getExtraValue(string $key, $default = null)
187
    {
188
        return $this->getExtra()[$key] ?? $default;
189
    }
190
191
    /**
192
     * @return array extra configuration array
193
     */
194
    private function getExtra(): array
195
    {
196
        return $this->getRawValue('extra') ?? $this->package->getExtra();
197
    }
198
199
    /**
200
     * @param string $name option name
201
     * @return mixed raw value from composer.json if available
202
     */
203
    private function getRawValue(string $name)
204
    {
205
        return $this->data[$name] ?? null;
206
    }
207
208
    /**
209
     * @return array composer.json contents as array
210
     * @throws \JsonException
211
     */
212
    private function readRawData(): array
213
    {
214
        $path = $this->preparePath(self::CONFIG_FILE_NAME_COMPOSER);
215
        if (file_exists($path)) {
216
            return json_decode(file_get_contents($path), true, 512, JSON_THROW_ON_ERROR);
217
        }
218
219
        return [];
220
    }
221
222
    /**
223
     * @return array .composer-config-plugin.php array config
224
     */
225
    private function readConfigFile(): array
226
    {
227
        $path = $this->preparePath(self::CONFIG_FILE_NAME_PLUGIN);
228
        return file_exists($path) ? require $path : [];
229
    }
230
231
    /**
232
     * Builds path inside of a package.
233
     *
234
     * @param string $file
235
     * @return string absolute paths will stay untouched
236
     */
237
    public function preparePath(string $file): string
238
    {
239
        if (0 === strncmp($file, '$', 1)) {
240
            return $file;
241
        }
242
243
        $skippable = 0 === strncmp($file, '?', 1) ? '?' : '';
244
        if ($skippable) {
245
            $file = substr($file, 1);
246
        }
247
248
        if (!$this->filesystem->isAbsolutePath($file)) {
249
            $prefix = $this->isRoot()
250
                ? $this->baseDir
251
                : $this->vendorDir . '/' . $this->getPrettyName();
252
            $file = $prefix . '/' . $file;
253
        }
254
255
        return $skippable . $this->filesystem->normalizePath($file);
256
    }
257
258
    public function getVendorDir(): string
259
    {
260
        return $this->vendorDir;
261
    }
262
263
    public function getBaseDir(): string
264
    {
265
        return $this->baseDir;
266
    }
267
}
268