Completed
Push — master ( 2ec9f0...d428ee )
by Andrii
30:10 queued 22:08
created

src/models/AssetPackage.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Asset Packagist.
4
 *
5
 * @link      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\Package\Link;
16
use Exception;
17
use Fxp\Composer\AssetPlugin\Repository\AssetVcsRepository;
18
use hiqdev\assetpackagist\components\Storage;
19
use hiqdev\assetpackagist\log\YiiLogIO;
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 YiiLogIO
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
    }
63
64
    /**
65
     * AssetPackage constructor.
66
     * @param string $type
67
     * @param string $name
68
     * @param array $config
69
     * @throws Exception
70
     */
71 1
    public function __construct($type, $name, $config = [])
72
    {
73 1
        parent::__construct($config);
74
75 1
        if (!$this->checkType($type)) {
76
            throw new Exception('wrong type');
77
        }
78 1
        if (!$this->checkName($name)) {
79
            throw new Exception('wrong name');
80
        }
81 1
        $this->_type = $type;
82 1
        $this->_name = $name;
83 1
    }
84
85
    public function getRegistry()
86
    {
87
        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
91
        return $this->_registry;
92
    }
93
94 1
    public function checkType($type)
95
    {
96 1
        return $type === 'bower' || $type === 'npm';
97
    }
98
99 1
    public function checkName($name)
100
    {
101 1
        return strlen($name) > 0;
102
    }
103
104 1
    public function getFullName()
105
    {
106 1
        return static::buildFullName($this->_type, $this->_name);
107
    }
108
109 1
    public static function buildFullName($type, $name)
110
    {
111 1
        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 YiiLogIO(),
160
                Yii::getAlias('@composer/composer.json'),
0 ignored issues
show
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 YiiLogIO();
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
        foreach ($repository->getPackages() as $package) {
237
            if ($package instanceof \Composer\Package\AliasPackage) {
238
                continue;
239
            }
240
241
            $version = $package->getPrettyVersion();
242
            $require = $this->prepareRequire($package->getRequires());
243
            $release = [
244
                'uid' => $this->prepareUid($version),
245
                'name' => $this->getNormalName(),
246
                'version' => $version,
247
                'version_normalized' => $package->getVersion(),
248
                'type' => $this->getType() . '-asset',
249
            ];
250
            if ($require) {
251
                $release['require'] = $require;
252
            }
253
            if ($package->getDistUrl()) {
254
                $release['dist'] = [
255
                    'type' => $package->getDistType(),
256
                    'url' => $package->getDistUrl(),
257
                    'reference' => $package->getDistReference(),
258
                ];
259
            }
260
            if ($package->getSourceUrl()) {
261
                $release['source'] = [
262
                    'type' => $package->getSourceType(),
263
                    'url' => $package->getSourceUrl(),
264
                    'reference' => $package->getSourceReference(),
265
                ];
266
            }
267
            if ((isset($release['dist']) && $release['dist']) || (isset($release['source']) && $release['source'])) {
268
                $releases[$version] = $release;
269
            }
270
        }
271
272
        return $releases;
273
    }
274
275
    /**
276
     * Prepares array of requires: name => constraint.
277
     * @param Link[] array of package requires
278
     * @return array
279
     */
280
    public function prepareRequire(array $links)
281
    {
282
        $requires = [];
283
        foreach ($links as $name => $link) {
284
            /** @var Link $link */
285
            $requires[$name] = $link->getPrettyConstraint();
286
        }
287
288
        return $requires;
289
    }
290
291
    public function prepareUid($version)
292
    {
293
        $known = $this->getSaved()->getRelease($version);
294
295
        return isset($known['uid']) ? $known['uid'] : $this->getStorage()->getNextId();
296
    }
297
298
    /**
299
     * @return array
300
     */
301
    public function getReleases()
302
    {
303
        return $this->_releases;
304
    }
305
306
    /**
307
     * @param $version
308
     * @return array
309
     */
310
    public function getRelease($version)
311
    {
312
        return isset($this->_releases[$version]) ? $this->_releases[$version] : [];
313
    }
314
315
    public function getSaved()
316
    {
317
        if ($this->_saved === null) {
318
            $this->_saved = static::findOne($this->getType(), $this->getName());
319
        }
320
321
        return $this->_saved;
322
    }
323
324
    /**
325
     * @return Storage
326
     */
327
    public function getStorage()
328
    {
329
        return Yii::$app->get('packageStorage');
330
    }
331
332
    /**
333
     * Returns the latest update time (UNIX Epoch).
334
     * @return int|null
335
     */
336
    public function getUpdateTime()
337
    {
338
        return $this->_updateTime;
339
    }
340
341
    /**
342
     * Package can be updated not more often than once in 10 min.
343
     * @return bool
344
     */
345
    public function canBeUpdated()
346
    {
347
        return time() - $this->getUpdateTime() > 60 * 10; // 10 min
348
    }
349
350
    /**
351
     * Whether tha package should be auth-updated (if it is older than 1 day).
352
     * @return bool
353
     */
354
    public function canAutoUpdate()
355
    {
356
        return time() - $this->getUpdateTime() > 60 * 60 * 24; // 1 day
357
    }
358
359
    /**
360
     * @return array
361
     */
362
    public function __sleep()
363
    {
364
        return ['_type', '_name', '_hash'];
365
    }
366
}
367