Package   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 248
Duplicated Lines 0 %

Test Coverage

Coverage 84.06%

Importance

Changes 0
Metric Value
wmc 31
eloc 55
dl 0
loc 248
ccs 58
cts 69
cp 0.8406
rs 9.92
c 0
b 0
f 0

24 Methods

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