Completed
Pull Request — master (#34)
by Edgard
02:13
created

AssetPackage::getRegistry()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
rs 9.4285
ccs 4
cts 4
cp 1
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
/**
3
 * Asset Packagist.
4
 *
5
 * @see      https://github.com/hiqdev/asset-packagist
6
 * @package   asset-packagist
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2016-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\assetpackagist\models;
12
13
use Composer\Composer;
14
use Composer\Factory;
15
use Composer\IO\NullIO;
16
use Composer\Package\Link;
17
use Exception;
18
use Fxp\Composer\AssetPlugin\Repository\AssetVcsRepository;
19
use hiqdev\assetpackagist\components\Storage;
20
use hiqdev\assetpackagist\registry\BowerRegistry;
21
use hiqdev\assetpackagist\registry\NpmRegistry;
22
use hiqdev\assetpackagist\registry\RegistryFactory;
23
use Yii;
24
use yii\base\Object;
25
26
class AssetPackage extends Object
27
{
28
    protected $_type;
29
    protected $_name;
30
    protected $_hash;
31
    /**
32
     * @var array
33
     */
34
    protected $_releases = [];
35
    protected $_saved;
36
    /**
37
     * @var AssetVcsRepository|BowerRegistry|NpmRegistry
38
     */
39
    protected $_registry;
40
41
    /**
42
     * @var integer UNIX Epoch timestamp of the latest package update
43
     */
44
    protected $_updateTime;
45
46
    /**
47
     * @var NullIO
48
     */
49
    protected $_io;
50
    /**
51
     * @var Composer
52
     */
53
    protected $_composer;
54
    /**
55
     * @var Composer
56
     */
57
    protected static $_commonComposer;
58
59
    public static function normalizeName($name)
60
    {
61
        return strtolower($name);
62 1
    }
63
64 1
    /**
65
     * AssetPackage constructor.
66 1
     * @param string $type
67
     * @param string $name
68
     * @param array $config
69 1
     * @throws Exception
70
     */
71
    public function __construct($type, $name, $config = [])
72 1
    {
73 1
        parent::__construct($config);
74 1
75
        if (!$this->checkType($type)) {
76
            throw new Exception('wrong type');
77
        }
78
        if (!$this->checkName($name)) {
79
            throw new Exception('wrong name');
80
        }
81
        $this->_type = $type;
82
        $this->_name = $name;
83
    }
84
85 1
    public function getRegistry()
86
    {
87 1
        if ($this->_registry === null) {
88
            $this->_registry = RegistryFactory::getRegistry($this->getType(), $this->getComposer()->getRepositoryManager());
0 ignored issues
show
Documentation Bug introduced by
It seems like \hiqdev\assetpackagist\r...getRepositoryManager()) of type object<Fxp\Composer\Asse...stractAssetsRepository> is incompatible with the declared type object<Fxp\Composer\Asse...t\registry\NpmRegistry> of property $_registry.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
89
        }
90 1
91
        return $this->_registry;
92 1
    }
93
94
    public function checkType($type)
95 1
    {
96
        return $type === 'bower' || $type === 'npm';
97 1
    }
98
99
    public function checkName($name)
100 1
    {
101
        return strlen($name) > 0;
102 1
    }
103
104
    public function getFullName()
105
    {
106
        return static::buildFullName($this->_type, $this->_name);
107
    }
108
109
    public static function buildFullName($type, $name)
110
    {
111
        return $type . '-asset/' . $name;
112
    }
113
114
    public static function splitFullName($full)
115
    {
116
        list($temp, $name) = explode('/', $full);
117
        list($type) = explode('-', $temp);
118
119
        return [$type, $name];
120
    }
121
122
    /**
123
     * @param string $full package name
124
     * @return static
125
     */
126
    public static function fromFullName($full)
127
    {
128
        list($type, $name) = static::splitFullName($full);
129
        return new static($type, $name);
130
    }
131
132
    public function getType()
133
    {
134
        return $this->_type;
135
    }
136
137
    public function getNormalName()
138
    {
139
        return static::buildFullName($this->_type, static::normalizeName($this->_name));
140
    }
141
142
    public function getName()
143
    {
144
        return $this->_name;
145
    }
146
147
    public function getHash()
148
    {
149
        return $this->_hash;
150
    }
151
152
    /**
153
     * @return Composer
154
     */
155
    public static function getCommonComposer()
156
    {
157
        if (static::$_commonComposer === null) {
158
            static::$_commonComposer = (new Factory())->createComposer(
159
                new NullIO(),
160
                Yii::getAlias('@composer/composer.json'),
0 ignored issues
show
Bug introduced by
It seems like \Yii::getAlias('@composer/composer.json') targeting yii\BaseYii::getAlias() can also be of type boolean; however, Composer\Factory::createComposer() does only seem to accept array|string|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
161
                false,
162
                Yii::getAlias('@composer')
163
            );
164
        }
165
166
        return static::$_commonComposer;
167
    }
168
169
    public function setComposer($value)
170
    {
171
        $this->_composer = $value;
172
    }
173
174
    /**
175
     * @return Composer
176
     */
177
    public function getComposer()
178
    {
179
        if ($this->_composer === null) {
180
            $this->_composer = static::getCommonComposer();
181
        }
182
183
        return $this->_composer;
184
    }
185
186
    public function getIO()
187
    {
188
        if ($this->_io === null) {
189
            $this->_io = new NullIO();
190
        }
191
192
        return $this->_io;
193
    }
194
195
    /**
196
     * findOne.
197
     *
198
     * @param string $type
199
     * @param string $name
200
     * @return static|null
201
     */
202
    public static function findOne($type, $name)
203
    {
204
        $package = new static($type, $name);
205
        $package->load();
206
207
        return $package;
208
    }
209
210
    public function load()
211
    {
212
        $data = $this->getStorage()->readPackage($this);
213
        if ($data !== null) {
214
            $this->_hash = $data['hash'];
215
            $this->_releases = $data['releases'];
216
            $this->_updateTime = $data['updateTime'];
217
        }
218
    }
219
220
    public function update()
221
    {
222
        $repo = $this->getRegistry()->buildVcsRepository($this->getName());
223
        $this->_releases = $this->prepareReleases($repo);
224
        $this->getStorage()->writePackage($this);
225
        $this->load();
226
    }
227
228
    /**
229
     * @param AssetVcsRepository $repository
230
     * @return array
231
     */
232
    public function prepareReleases($repository)
233
    {
234
        $releases = [];
235
236
        /* @var $package \Fxp\Composer\AssetPlugin\Package\AbstractLazyCompletePackage */
237
        foreach ($repository->getPackages() as $package) {
238
            $version = $package->getPrettyVersion();
239
            $require = $this->prepareRequire($package->getRequires());
240
            $type = $this->getType() . '-asset';
241
            $release = [
242
                'uid' => $this->prepareUid($version),
243
                'name' => $this->getNormalName(),
244
                'version' => $version,
245
                'version_normalized' => $package->getVersion(),
246
                'type' => $type,
247
            ];
248
            if ($require) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $require of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
249
                $release['require'] = $require;
250
            }
251
            $extra = $package->getExtra();
252
            if ($extra && isset($extra['branch-alias'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $extra of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
253
                $release['extra'] = ['branch-alias' => $extra['branch-alias']];
254
            }
255
            if ($package->getDistUrl()) {
256
                $release['dist'] = [
257
                    'type' => $package->getDistType(),
258
                    'url' => $package->getDistUrl(),
259
                    'reference' => $package->getDistReference(),
260
                ];
261
            }
262
            if ($package->getSourceUrl()) {
263
                $release['source'] = [
264
                    'type' => $package->getSourceType(),
265
                    'url' => $package->getSourceUrl(),
266
                    'reference' => $package->getSourceReference(),
267
                ];
268
            }
269
            if ((isset($release['dist']) && $release['dist']) || (isset($release['source']) && $release['source'])) {
270
                $releases[$version] = $release;
271
            }
272
        }
273
274
        return $releases;
275
    }
276
277
    /**
278
     * Prepares array of requires: name => constraint.
279
     * @param Link[] array of package requires
280
     * @return array
281
     */
282
    public function prepareRequire(array $links)
283
    {
284
        $requires = [];
285
        foreach ($links as $name => $link) {
286
            /** @var Link $link */
287
            $requires[$name] = $link->getPrettyConstraint();
288
        }
289
290
        return $requires;
291
    }
292
293
    public function prepareUid($version)
294
    {
295
        $known = $this->getSaved()->getRelease($version);
296
297
        return isset($known['uid']) ? $known['uid'] : $this->getStorage()->getNextId();
298
    }
299
300
    /**
301
     * @return array
302
     */
303
    public function getReleases()
304
    {
305
        return $this->_releases;
306
    }
307
308
    /**
309
     * @param $version
310
     * @return array
311
     */
312
    public function getRelease($version)
313
    {
314
        return isset($this->_releases[$version]) ? $this->_releases[$version] : [];
315
    }
316
317
    public function getSaved()
318
    {
319
        if ($this->_saved === null) {
320
            $this->_saved = static::findOne($this->getType(), $this->getName());
321
        }
322
323
        return $this->_saved;
324
    }
325
326
    /**
327
     * @return Storage
328
     */
329
    public function getStorage()
330
    {
331
        return Yii::$app->get('packageStorage');
332
    }
333
334
    /**
335
     * Returns the latest update time (UNIX Epoch).
336
     * @return int|null
337
     */
338
    public function getUpdateTime()
339
    {
340
        return $this->_updateTime;
341
    }
342
343
    /**
344
     * Package can be updated not more often than once in 10 min.
345
     * @return bool
346
     */
347
    public function canBeUpdated()
348
    {
349
        return time() - $this->getUpdateTime() > 60 * 10; // 10 min
350
    }
351
352
    /**
353
     * Whether tha package should be auth-updated (if it is older than 1 day).
354
     * @return bool
355
     */
356
    public function canAutoUpdate()
357
    {
358
        return time() - $this->getUpdateTime() > 60 * 60 * 24; // 1 day
359
    }
360
361
    /**
362
     * @return array
363
     */
364
    public function __sleep()
365
    {
366
        return ['_type', '_name', '_hash'];
367
    }
368
}
369