Completed
Pull Request — master (#34)
by Dmitry
52:52 queued 37:59
created

AssetPackage::getUpdateTime()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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