Completed
Push — master ( 5a29a0...22ab66 )
by Dmitry
10:00
created

AssetPackage::fromFullName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 2
cp 0
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
3
/*
4
 * Asset Packagist
5
 *
6
 * @link      https://github.com/hiqdev/asset-packagist
7
 * @package   asset-packagist
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hiqdev\assetpackagist\models;
13
14
use Composer\Composer;
15
use Composer\Factory;
16
use Composer\IO\NullIO;
17
use Composer\Package\Link;
18
use Exception;
19
use Fxp\Composer\AssetPlugin\Repository\AssetVcsRepository;
20
use hiqdev\assetpackagist\components\Storage;
21
use hiqdev\assetpackagist\registry\BowerRegistry;
22
use hiqdev\assetpackagist\registry\NpmRegistry;
23
use hiqdev\assetpackagist\registry\RegistryFactory;
24
use Yii;
25
use yii\base\Object;
26
27
class AssetPackage extends Object
28
{
29
    protected $_type;
30
    protected $_name;
31
    protected $_hash;
32
    /**
33
     * @var array
34
     */
35
    protected $_releases = [];
36
    protected $_saved;
37
    /**
38
     * @var AssetVcsRepository|BowerRegistry|NpmRegistry
39
     */
40
    protected $_registry;
41
42
    /**
43
     * @var integer UNIX Epoch timestamp of the latest package update
44
     */
45
    protected $_updateTime;
46
47
    /**
48
     * @var NullIO
49
     */
50
    protected $_io;
51
    /**
52
     * @var Composer
53
     */
54
    protected $_composer;
55
    /**
56
     * @var Composer
57
     */
58
    protected static $_commonComposer;
59
60
    public static function normalizeName($name)
61
    {
62 1
        return strtolower($name);
63
    }
64 1
65
    public function __construct($type, $name, $config = [])
66 1
    {
67
        parent::__construct($config);
68
69 1
        if (!$this->checkType($type)) {
70
            throw new Exception('wrong type');
71
        }
72 1
        if (!$this->checkName($name)) {
73 1
            throw new Exception('wrong name');
74 1
        }
75
        $this->_type = $type;
76
        $this->_name = $name;
77
    }
78
79
    public function getRegistry()
80
    {
81
        if ($this->_registry === null) {
82
            $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...
83
        }
84
85 1
        return $this->_registry;
86
    }
87 1
88
    public function checkType($type)
89
    {
90 1
        return $type === 'bower' || $type === 'npm';
91
    }
92 1
93
    public function checkName($name)
94
    {
95 1
        return strlen($name) > 0;
96
    }
97 1
98
    public function getFullName()
99
    {
100 1
        return static::buildFullName($this->_type, $this->_name);
101
    }
102 1
103
    public static function buildFullName($type, $name)
104
    {
105
        return $type . '-asset/' . $name;
106
    }
107
108
    public static function splitFullName($full)
109
    {
110
        list($temp, $name) = explode('/', $full);
111
        list($type) = explode('-', $temp);
112
113
        return [$type, $name];
114
    }
115
116
    /**
117
     * @param string $full package name
118
     * @return static
119
     */
120
    public static function fromFullName($full)
121
    {
122
        list($type, $name) = static::splitFullName($full);
123
        return new static($type, $name);
124
    }
125
126
    public function getType()
127
    {
128
        return $this->_type;
129
    }
130
131
    public function getNormalName()
132
    {
133
        return static::buildFullName($this->_type, static::normalizeName($this->_name));
134
    }
135
136
    public function getName()
137
    {
138
        return $this->_name;
139
    }
140
141
    public function getHash()
142
    {
143
        return $this->_hash;
144
    }
145
146
    /**
147
     * @return Composer
148
     */
149
    public static function getCommonComposer()
150
    {
151
        if (static::$_commonComposer === null) {
152
            static::$_commonComposer = (new Factory())->createComposer(
153
                new NullIO(),
154
                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...
155
                false,
156
                Yii::getAlias('@composer')
157
            );
158
        }
159
160
        return static::$_commonComposer;
161
    }
162
163
    public function setComposer($value)
164
    {
165
        $this->_composer = $value;
166
    }
167
168
    /**
169
     * @return Composer
170
     */
171
    public function getComposer()
172
    {
173
        if ($this->_composer === null) {
174
            $this->_composer = static::getCommonComposer();
175
        }
176
177
        return $this->_composer;
178
    }
179
180
    public function getIO()
181
    {
182
        if ($this->_io === null) {
183
            $this->_io = new NullIO();
184
        }
185
186
        return $this->_io;
187
    }
188
189
    /**
190
     * findOne.
191
     *
192
     * @param string $type
193
     * @param string $name
194
     * @return static|null
195
     */
196
    public static function findOne($type, $name)
197
    {
198
        $package = new static($type, $name);
199
        $package->load();
200
201
        return $package;
202
    }
203
204
    public function load()
205
    {
206
        $data = $this->getStorage()->readPackage($this);
207
        if ($data !== null) {
208
            $this->_hash = $data['hash'];
209
            $this->_releases = $data['releases'];
210
            $this->_updateTime = $data['updateTime'];
211
        }
212
    }
213
214
    public function update()
215
    {
216
        $repo = $this->getRegistry()->buildVcsRepository($this->getName());
217
        $this->_releases = $this->prepareReleases($repo);
218
        $this->_hash = $this->getStorage()->writePackage($this);
219
    }
220
221
    /**
222
     * @param AssetVcsRepository $repository
223
     * @return array
224
     */
225
    public function prepareReleases($repository)
226
    {
227
        $releases = [];
228
229
        foreach ($repository->getPackages() as $package) {
230
            $version = $package->getVersion();
231
            $require = $this->prepareRequire($package->getRequires());
232
            $release = [
233
                'uid' => $this->prepareUid($version),
234
                'name' => $this->getNormalName(),
235
                'version' => $version,
236
            ];
237
            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...
238
                $release['require'] = $require;
239
            }
240
            if ($package->getDistUrl()) {
241
                $release['dist'] = [
242
                    'type' => $package->getDistType(),
243
                    'url' => $package->getDistUrl(),
244
                    'reference' => $package->getDistReference(),
245
                ];
246
            }
247
            if ($package->getSourceUrl()) {
248
                $release['source'] = [
249
                    'type' => $package->getSourceType(),
250
                    'url' => $package->getSourceUrl(),
251
                    'reference' => $package->getSourceReference(),
252
                ];
253
            }
254
            if ((isset($release['dist']) && $release['dist']) || (isset($release['source']) && $release['source'])) {
255
                $releases[$version] = $release;
256
            }
257
        }
258
259
        return $releases;
260
    }
261
262
    /**
263
     * Prepares array of requires: name => constraint.
264
     * @param Link[] array of package requires.
265
     * @return array
266
     */
267
    public function prepareRequire(array $links)
268
    {
269
        $requires = [];
270
        foreach ($links as $name => $link) {
271
            /** @var Link $link */
272
            $requires[$name] = $link->getPrettyConstraint();
273
        }
274
275
        return $requires;
276
    }
277
278
    public function prepareUid($version)
279
    {
280
        $known = $this->getSaved()->getRelease($version);
281
282
        return isset($known['uid']) ? $known['uid'] : $this->getStorage()->getNextID();
283
    }
284
285
    /**
286
     * @return array
287
     */
288
    public function getReleases()
289
    {
290
        return $this->_releases;
291
    }
292
293
    /**
294
     * @param $version
295
     * @return array
296
     */
297
    public function getRelease($version)
298
    {
299
        return isset($this->_releases[$version]) ? $this->_releases[$version] : [];
300
    }
301
302
    public function getSaved()
303
    {
304
        if ($this->_saved === null) {
305
            $this->_saved = static::findOne($this->getType(), $this->getName());
306
        }
307
308
        return $this->_saved;
309
    }
310
311
    /**
312
     * @return Storage
313
     */
314
    public function getStorage()
315
    {
316
        return Yii::$app->get('packageStorage');
317
    }
318
319
    /**
320
     * Returns the latest update time (UNIX Epoch).
321
     * @return int|null
322
     */
323
    public function getUpdateTime()
324
    {
325
        return $this->_updateTime;
326
    }
327
328
    /**
329
     * Package can be updated not more often than once in 10 min.
330
     * @return bool
331
     */
332
    public function canBeUpdated()
333
    {
334
        return time() - $this->getUpdateTime() > 60 * 10; // 10 min
335
    }
336
337
    /**
338
     * Whether tha package should be auth-updated (if it is older than 1 day).
339
     * @return bool
340
     */
341
    public function canAutoUpdate()
342
    {
343
        return time() - $this->getUpdateTime() > 60 * 60 * 24; // 1 day
344
    }
345
346
    /**
347
     * @return array
348
     */
349
    public function __sleep()
350
    {
351
        return ['_type', '_name', '_hash'];
352
    }
353
}
354