Passed
Pull Request — master (#111)
by
unknown
14:42
created

Package::isComplete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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