Passed
Push — master ( 77a8ea...8a6a58 )
by Andrii
10:48
created

Package::getFiles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * Composer plugin for config assembling
4
 *
5
 * @link      https://github.com/hiqdev/composer-config-plugin
6
 * @package   composer-config-plugin
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2016-2018, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\composer\config;
12
13
use Composer\Composer;
14
use Composer\Package\CompletePackageInterface;
15
use Composer\Package\PackageInterface;
16
use Composer\Package\RootPackageInterface;
17
use Composer\Util\Filesystem;
18
19
/**
20
 * Class Package.
21
 * @author Andrii Vasyliev <[email protected]>
22
 */
23
class Package
24
{
25
    const EXTRA_FILES_OPTION_NAME           = 'config-plugin';
26
    const EXTRA_DEV_FILES_OPTION_NAME       = 'config-plugin-dev';
27
    const EXTRA_OUTPUT_DIR_OPTION_NAME      = 'config-plugin-output-dir';
28
    const EXTRA_ALTERNATIVES_OPTION_NAME    = 'config-plugin-alternatives';
29
30
    private $options = ['output-dir', 'alternatives'];
0 ignored issues
show
introduced by
The private property $options is not used, and could be removed.
Loading history...
31
32
    protected $package;
33
34
    /**
35
     * @var array composer.json raw data array
36
     */
37
    protected $data;
38
39
    /**
40
     * @var string absolute path to the root base directory
41
     */
42
    protected $baseDir;
43
44
    /**
45
     * @var string absolute path to vendor directory
46
     */
47
    protected $vendorDir;
48
49
    /**
50
     * @var Filesystem utility
51
     */
52
    protected $filesystem;
53
54
    private $composer;
55
56
    public function __construct(PackageInterface $package, Composer $composer)
57
    {
58
        $this->package = $package;
59
        $this->composer = $composer;
60
    }
61
62
    /**
63
     * Collects package aliases.
64
     * @return array collected aliases
65
     */
66
    public function collectAliases(): array
67
    {
68
        $aliases = array_merge(
69
            $this->prepareAliases('psr-0'),
70
            $this->prepareAliases('psr-4')
71
        );
72
        if ($this->isRoot()) {
73
            $aliases = array_merge($aliases,
74
                $this->prepareAliases('psr-0', true),
75
                $this->prepareAliases('psr-4', true)
76
            );
77
        }
78
79
        return $aliases;
80
    }
81
82
    /**
83
     * Prepare aliases.
84
     * @param string 'psr-0' or 'psr-4'
0 ignored issues
show
Documentation Bug introduced by
The doc comment 'psr-0' at position 0 could not be parsed: Unknown type name ''psr-0'' at position 0 in 'psr-0'.
Loading history...
85
     * @param bool $dev
86
     * @return array
87
     */
88
    protected function prepareAliases($psr, $dev = false)
89
    {
90
        $autoload = $dev ? $this->getDevAutoload() : $this->getAutoload();
91
        if (empty($autoload[$psr])) {
92
            return [];
93
        }
94
95
        $aliases = [];
96
        foreach ($autoload[$psr] as $name => $path) {
97
            if (is_array($path)) {
98
                // ignore psr-4 autoload specifications with multiple search paths
99
                // we can not convert them into aliases as they are ambiguous
100
                continue;
101
            }
102
            $name = str_replace('\\', '/', trim($name, '\\'));
103
            $path = $this->preparePath($path);
104
            if ('psr-0' === $psr) {
105
                $path .= '/' . $name;
106
            }
107
            $aliases["@$name"] = $path;
108
        }
109
110
        return $aliases;
111
    }
112
113
    /**
114
     * @return string package pretty name, like: vendor/name
115
     */
116
    public function getPrettyName(): string
117
    {
118
        return $this->package->getPrettyName();
119
    }
120
121
    /**
122
     * @return string package version, like: 3.0.16.0, 9999999-dev
123
     */
124
    public function getVersion(): string
125
    {
126
        return $this->package->getVersion();
127
    }
128
129
    /**
130
     * @return string package human friendly version, like: 5.x-dev d9aed42, 2.1.1, dev-master f6561bf
131
     */
132
    public function getFullPrettyVersion(): string
133
    {
134
        return $this->package->getFullPrettyVersion();
135
    }
136
137
    /**
138
     * @return string package CVS revision, like: 3a4654ac9655f32888efc82fb7edf0da517d8995
139
     */
140
    public function getSourceReference(): ?string
141
    {
142
        return $this->package->getSourceReference();
143
    }
144
145
    /**
146
     * @return string package dist revision, like: 3a4654ac9655f32888efc82fb7edf0da517d8995
147
     */
148
    public function getDistReference(): ?string
149
    {
150
        return $this->package->getDistReference();
151
    }
152
153
    /**
154
     * @return bool is package complete
155
     */
156
    public function isComplete(): bool
157
    {
158
        return $this->package instanceof CompletePackageInterface;
159
    }
160
161
    /**
162
     * @return bool is this a root package
163
     */
164
    public function isRoot(): bool
165
    {
166
        return $this->package instanceof RootPackageInterface;
167
    }
168
169
    /**
170
     * @return string package type, like: package, library
171
     */
172
    public function getType(): string
173
    {
174
        return $this->getRawValue('type') ?? $this->package->getType();
175
    }
176
177
    /**
178
     * @return array autoload configuration array
179
     */
180
    public function getAutoload(): array
181
    {
182
        return $this->getRawValue('autoload') ?? $this->package->getAutoload();
183
    }
184
185
    /**
186
     * @return array autoload-dev configuration array
187
     */
188
    public function getDevAutoload(): array
189
    {
190
        return $this->getRawValue('autoload-dev') ?? $this->package->getDevAutoload();
191
    }
192
193
    /**
194
     * @return array requre configuration array
195
     */
196
    public function getRequires(): array
197
    {
198
        return $this->getRawValue('require') ?? $this->package->getRequires();
199
    }
200
201
    /**
202
     * @return array requre-dev configuration array
203
     */
204
    public function getDevRequires(): array
205
    {
206
        return $this->getRawValue('require-dev') ?? $this->package->getDevRequires();
207
    }
208
209
    /**
210
     * @return array files array
211
     */
212
    public function getFiles(): array
213
    {
214
        return $this->getExtraValue(self::EXTRA_FILES_OPTION_NAME, []);
215
    }
216
217
    /**
218
     * @return array dev-files array
219
     */
220
    public function getDevFiles(): array
221
    {
222
        return $this->getExtraValue(self::EXTRA_DEV_FILES_OPTION_NAME, []);
223
    }
224
225
    /**
226
     * @return array output-dir option
227
     */
228
    public function getOutputDir(): ?string
229
    {
230
        return $this->getExtraValue(self::EXTRA_OUTPUT_DIR_OPTION_NAME);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getExtraVa...OUTPUT_DIR_OPTION_NAME) returns the type array which is incompatible with the type-hinted return null|string.
Loading history...
231
    }
232
233
    /**
234
     * @return array alternatives array
235
     */
236
    public function getAlternatives(): array
237
    {
238
        return $this->getExtraValue(self::EXTRA_ALTERNATIVES_OPTION_NAME, []);
239
    }
240
241
    /**
242
     * @return array alternatives array
243
     */
244
    public function getExtraValue($key, $default = null)
245
    {
246
        return $this->getExtra()[$key] ?? $default;
247
    }
248
249
    /**
250
     * @return array extra configuration array
251
     */
252
    public function getExtra(): array
253
    {
254
        return $this->getRawValue('extra') ?? $this->package->getExtra();
255
    }
256
257
    /**
258
     * @param string $name option name
259
     * @return mixed raw value from composer.json if available
260
     */
261
    public function getRawValue(string $name)
262
    {
263
        if ($this->data === null) {
264
            $this->data = $this->readRawData();
265
        }
266
267
        return $this->data[$name] ?? null;
268
    }
269
270
    /**
271
     * @return mixed all raw data from composer.json if available
272
     */
273
    public function getRawData(): array
274
    {
275
        if ($this->data === null) {
276
            $this->data = $this->readRawData();
277
        }
278
279
        return $this->data;
280
    }
281
282
    /**
283
     * @return array composer.json contents as array
284
     */
285
    protected function readRawData(): array
286
    {
287
        $path = $this->preparePath('composer.json');
288
        if (file_exists($path)) {
289
            return json_decode(file_get_contents($path), true);
290
        }
291
292
        return [];
293
    }
294
295
    /**
296
     * Builds path inside of a package.
297
     * @param string $file
298
     * @return string absolute paths will stay untouched
299
     */
300
    public function preparePath(string $file): string
301
    {
302
        if (0 === strncmp($file, '$', 1)) {
303
            return $file;
304
        }
305
306
        $skippable = 0 === strncmp($file, '?', 1) ? '?' : '';
307
        if ($skippable) {
308
            $file = substr($file, 1);
309
        }
310
311
        if (!$this->getFilesystem()->isAbsolutePath($file)) {
312
            $prefix = $this->isRoot()
313
                ? $this->getBaseDir()
314
                : $this->getVendorDir() . '/' . $this->getPrettyName();
315
            $file = $prefix . '/' . $file;
316
        }
317
318
        return $skippable . $this->getFilesystem()->normalizePath($file);
319
    }
320
321
    /**
322
     * Get absolute path to package base dir.
323
     * @return string
324
     */
325
    public function getBaseDir()
326
    {
327
        if (null === $this->baseDir) {
328
            $this->baseDir = dirname($this->getVendorDir());
329
        }
330
331
        return $this->baseDir;
332
    }
333
334
    /**
335
     * Get absolute path to composer vendor dir.
336
     * @return string
337
     */
338
    public function getVendorDir()
339
    {
340
        if (null === $this->vendorDir) {
341
            $dir = $this->composer->getConfig()->get('vendor-dir');
342
            $this->vendorDir = $this->getFilesystem()->normalizePath($dir);
343
        }
344
345
        return $this->vendorDir;
346
    }
347
348
    /**
349
     * Getter for filesystem utility.
350
     * @return Filesystem
351
     */
352
    public function getFilesystem()
353
    {
354
        if (null === $this->filesystem) {
355
            $this->filesystem = new Filesystem();
356
        }
357
358
        return $this->filesystem;
359
    }
360
}
361