Completed
Push — master ( 8844c6...a7acd5 )
by Nicolas
05:21
created

Repository::boot()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
crap 2.0625
1
<?php
2
3
namespace Nwidart\Modules;
4
5
use Countable;
6
use Illuminate\Foundation\Application;
7
use Illuminate\Support\Str;
8
use Nwidart\Modules\Contracts\RepositoryInterface;
9
use Nwidart\Modules\Exceptions\ModuleNotFoundException;
10
use Nwidart\Modules\Process\Installer;
11
use Nwidart\Modules\Process\Updater;
12
13
class Repository implements RepositoryInterface, Countable
14
{
15
    /**
16
     * Application instance.
17
     *
18
     * @var Application
19
     */
20
    protected $app;
21
22
    /**
23
     * The module path.
24
     *
25
     * @var string|null
26
     */
27
    protected $path;
28
29
    /**
30
     * The scanned paths.
31
     *
32
     * @var array
33
     */
34
    protected $paths = [];
35
36
    /**
37
     * @var string
38
     */
39
    protected $stubPath;
40
41
    /**
42
     * The constructor.
43
     *
44
     * @param Application $app
45
     * @param string|null $path
46
     */
47 63
    public function __construct(Application $app, $path = null)
48
    {
49 63
        $this->app = $app;
50 63
        $this->path = $path;
51 63
    }
52
53
    /**
54
     * Add other module location.
55
     *
56
     * @param string $path
57
     *
58
     * @return $this
59
     */
60 12
    public function addLocation($path)
61
    {
62 12
        $this->paths[] = $path;
63
64 12
        return $this;
65
    }
66
67
    /**
68
     * Alternative method for "addPath".
69
     *
70
     * @param string $path
71
     *
72
     * @return $this
73
     */
74 1
    public function addPath($path)
75
    {
76 1
        return $this->addLocation($path);
77
    }
78
79
    /**
80
     * Get all additional paths.
81
     *
82
     * @return array
83
     */
84 1
    public function getPaths()
85
    {
86 1
        return $this->paths;
87
    }
88
89
    /**
90
     * Get scanned modules paths.
91
     *
92
     * @return array
93
     */
94 63
    public function getScanPaths()
95
    {
96 63
        $paths = $this->paths;
97
98 63
        $paths[] = $this->getPath().'/*';
99
100 63
        if ($this->config('scan.enabled')) {
101
            $paths = array_merge($paths, $this->config('scan.paths'));
102
        }
103
104 63
        return $paths;
105
    }
106
107
    /**
108
     * Get & scan all modules.
109
     *
110
     * @return array
111
     */
112 63
    public function scan()
113
    {
114 63
        $paths = $this->getScanPaths();
115
116 63
        $modules = [];
117
118 63
        foreach ($paths as $key => $path) {
119 63
            $manifests = $this->app['files']->glob("{$path}/module.json");
120
121 63
            is_array($manifests) || $manifests = [];
122
123 63
            foreach ($manifests as $manifest) {
124 31
                $name = Json::make($manifest)->get('name');
125
126 31
                $lowerName = strtolower($name);
127
128 63
                $modules[$name] = new Module($this->app, $lowerName, dirname($manifest));
129
            }
130
        }
131
132 63
        return $modules;
133
    }
134
135
    /**
136
     * Get all modules.
137
     *
138
     * @return array
139
     */
140 63
    public function all()
141
    {
142 63
        if (!$this->config('cache.enabled')) {
143 63
            return $this->scan();
144
        }
145
146
        return $this->formatCached($this->getCached());
147
    }
148
149
    /**
150
     * Format the cached data as array of modules.
151
     *
152
     * @param array $cached
153
     *
154
     * @return array
155
     */
156
    protected function formatCached($cached)
157
    {
158
        $modules = [];
159
160
        foreach ($cached as $name => $module) {
161
            $path = $this->config('paths.modules').'/'.$name;
162
163
            $lowerName = strtolower($name);
164
165
            $modules[$name] = new Module($this->app, $lowerName, $path);
166
        }
167
168
        return $modules;
169
    }
170
171
    /**
172
     * Get cached modules.
173
     *
174
     * @return array
175
     */
176
    public function getCached()
177
    {
178
        return $this->app['cache']->remember($this->config('cache.key'), $this->config('cache.lifetime'), function () {
179
            return $this->toCollection()->toArray();
180
        });
181
    }
182
183
    /**
184
     * Get all modules as collection instance.
185
     *
186
     * @return Collection
187
     */
188 1
    public function toCollection()
189
    {
190 1
        return new Collection($this->scan());
191
    }
192
193
    /**
194
     * Get modules by status.
195
     *
196
     * @param $status
197
     *
198
     * @return array
199
     */
200 63
    public function getByStatus($status)
201
    {
202 63
        $modules = [];
203
204 63
        foreach ($this->all() as $name => $module) {
205 3
            if ($module->isStatus($status)) {
206 3
                $modules[$name] = $module;
207
            }
208
        }
209
210 63
        return $modules;
211
    }
212
213
    /**
214
     * Determine whether the given module exist.
215
     *
216
     * @param $name
217
     *
218
     * @return bool
219
     */
220 21
    public function has($name)
221
    {
222 21
        return array_key_exists($name, $this->all());
223
    }
224
225
    /**
226
     * Get list of enabled modules.
227
     *
228
     * @return array
229
     */
230 63
    public function enabled()
231
    {
232 63
        return $this->getByStatus(1);
233
    }
234
235
    /**
236
     * Get list of disabled modules.
237
     *
238
     * @return array
239
     */
240 1
    public function disabled()
241
    {
242 1
        return $this->getByStatus(0);
243
    }
244
245
    /**
246
     * Get count from all modules.
247
     *
248
     * @return int
249
     */
250 1
    public function count()
251
    {
252 1
        return count($this->all());
253
    }
254
255
    /**
256
     * Get all ordered modules.
257
     *
258
     * @param string $direction
259
     *
260
     * @return array
261
     */
262 63
    public function getOrdered($direction = 'asc')
263
    {
264 63
        $modules = $this->enabled();
265
266 63
        uasort($modules, function (Module $a, Module $b) use ($direction) {
267
            if ($a->order == $b->order) {
0 ignored issues
show
Documentation introduced by
The property order does not exist on object<Nwidart\Modules\Module>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
268
                return 0;
269
            }
270
271
            if ($direction == 'desc') {
272
                return $a->order < $b->order ? 1 : -1;
0 ignored issues
show
Documentation introduced by
The property order does not exist on object<Nwidart\Modules\Module>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
273
            }
274
275
            return $a->order > $b->order ? 1 : -1;
0 ignored issues
show
Documentation introduced by
The property order does not exist on object<Nwidart\Modules\Module>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
276 63
        });
277
278 63
        return $modules;
279
    }
280
281
    /**
282
     * Get a module path.
283
     *
284
     * @return string
285
     */
286 63
    public function getPath()
287
    {
288 63
        return $this->path ?: $this->config('paths.modules');
289
    }
290
291
    /**
292
     * Register the modules.
293
     */
294 63
    public function register()
295
    {
296 63
        foreach ($this->getOrdered() as $module) {
297
            $module->register();
298
        }
299 63
    }
300
301
    /**
302
     * Boot the modules.
303
     */
304 63
    public function boot()
305
    {
306 63
        foreach ($this->getOrdered() as $module) {
307
            $module->boot();
308
        }
309 63
    }
310
311
    /**
312
     * Find a specific module.
313
     * @param $name
314
     * @return mixed|void
315
     */
316 28
    public function find($name)
317
    {
318 28
        foreach ($this->all() as $module) {
319 27
            if ($module->getLowerName() === strtolower($name)) {
320 27
                return $module;
321
            }
322
        }
323
324 22
        return;
325
    }
326
327
    /**
328
     * Alternative for "find" method.
329
     * @param $name
330
     * @return mixed|void
331
     */
332 1
    public function get($name)
333
    {
334 1
        return $this->find($name);
335
    }
336
337
    /**
338
     * Find a specific module, if there return that, otherwise throw exception.
339
     *
340
     * @param $name
341
     *
342
     * @return Module
343
     *
344
     * @throws ModuleNotFoundException
345
     */
346 27
    public function findOrFail($name)
347
    {
348 27
        $module = $this->find($name);
349
350 27
        if ($module !== null) {
351 26
            return $module;
352
        }
353
354 22
        throw new ModuleNotFoundException("Module [{$name}] does not exist!");
355
    }
356
357
    /**
358
     * Get all modules as laravel collection instance.
359
     *
360
     * @return Collection
361
     */
362 1
    public function collections()
363
    {
364 1
        return new Collection($this->enabled());
365
    }
366
367
    /**
368
     * Get module path for a specific module.
369
     *
370
     * @param $module
371
     *
372
     * @return string
373
     */
374 21
    public function getModulePath($module)
375
    {
376
        try {
377 21
            return $this->findOrFail($module)->getPath().'/';
378 21
        } catch (ModuleNotFoundException $e) {
379 21
            return $this->getPath().'/'.Str::studly($module).'/';
380
        }
381
    }
382
383
    /**
384
     * Get asset path for a specific module.
385
     *
386
     * @param $module
387
     *
388
     * @return string
389
     */
390 2
    public function assetPath($module)
391
    {
392 2
        return $this->config('paths.assets').'/'.$module;
393
    }
394
395
    /**
396
     * Get a specific config data from a configuration file.
397
     *
398
     * @param $key
399
     *
400
     * @return mixed
401
     */
402 63
    public function config($key)
403
    {
404 63
        return $this->app['config']->get('modules.'.$key);
405
    }
406
407
    /**
408
     * Get storage path for module used.
409
     *
410
     * @return string
411
     */
412 2
    public function getUsedStoragePath()
413
    {
414 2
        if (!$this->app['files']->exists($path = storage_path('app/modules'))) {
415 1
            $this->app['files']->makeDirectory($path, 0777, true);
416
        }
417
418 2
        return $path.'/modules.used';
419
    }
420
421
    /**
422
     * Set module used for cli session.
423
     *
424
     * @param $name
425
     *
426
     * @throws ModuleNotFoundException
427
     */
428 1
    public function setUsed($name)
429
    {
430 1
        $module = $this->findOrFail($name);
431
432 1
        $this->app['files']->put($this->getUsedStoragePath(), $module);
433 1
    }
434
435
    /**
436
     * Get module used for cli session.
437
     *
438
     * @return string
439
     */
440 1
    public function getUsedNow()
441
    {
442 1
        return $this->findOrFail($this->app['files']->get($this->getUsedStoragePath()));
443
    }
444
445
    /**
446
     * Get used now.
447
     *
448
     * @return string
449
     */
450 1
    public function getUsed()
451
    {
452 1
        return $this->getUsedNow();
453
    }
454
455
    /**
456
     * Get laravel filesystem instance.
457
     *
458
     * @return \Illuminate\Filesystem\Filesystem
459
     */
460 4
    public function getFiles()
461
    {
462 4
        return $this->app['files'];
463
    }
464
465
    /**
466
     * Get module assets path.
467
     *
468
     * @return string
469
     */
470 2
    public function getAssetsPath()
471
    {
472 2
        return $this->config('paths.assets');
473
    }
474
475
    /**
476
     * Get asset url from a specific module.
477
     *
478
     * @param string $asset
479
     *
480
     * @return string
481
     */
482 1
    public function asset($asset)
483
    {
484 1
        list($name, $url) = explode(':', $asset);
485
486 1
        $baseUrl = str_replace(public_path(), '', $this->getAssetsPath());
487
488 1
        $url = $this->app['url']->asset($baseUrl."/{$name}/".$url);
489
490 1
        return str_replace(['http://', 'https://'], '//', $url);
491
    }
492
493
    /**
494
     * Determine whether the given module is activated.
495
     *
496
     * @param string $name
497
     *
498
     * @return bool
499
     */
500 4
    public function active($name)
501
    {
502 4
        return $this->findOrFail($name)->active();
503
    }
504
505
    /**
506
     * Determine whether the given module is not activated.
507
     *
508
     * @param string $name
509
     *
510
     * @return bool
511
     */
512 2
    public function notActive($name)
513
    {
514 2
        return !$this->active($name);
515
    }
516
517
    /**
518
     * Enabling a specific module.
519
     *
520
     * @param string $name
521
     *
522
     * @return bool
523
     */
524 1
    public function enable($name)
525
    {
526 1
        return $this->findOrFail($name)->enable();
527
    }
528
529
    /**
530
     * Disabling a specific module.
531
     *
532
     * @param string $name
533
     *
534
     * @return bool
535
     */
536 1
    public function disable($name)
537
    {
538 1
        return $this->findOrFail($name)->disable();
539
    }
540
541
    /**
542
     * Delete a specific module.
543
     *
544
     * @param string $name
545
     *
546
     * @return bool
547
     */
548 1
    public function delete($name)
549
    {
550 1
        return $this->findOrFail($name)->delete();
551
    }
552
553
    /**
554
     * Update dependencies for the specified module.
555
     *
556
     * @param string $module
557
     */
558
    public function update($module)
559
    {
560
        with(new Updater($this))->update($module);
561
    }
562
563
    /**
564
     * Install the specified module.
565
     *
566
     * @param string $name
567
     * @param string $version
568
     * @param string $type
569
     * @param bool   $subtree
570
     *
571
     * @return \Symfony\Component\Process\Process
572
     */
573
    public function install($name, $version = 'dev-master', $type = 'composer', $subtree = false)
574
    {
575
        $installer = new Installer($name, $version, $type, $subtree);
576
577
        return $installer->run();
578
    }
579
580
    /**
581
     * Get stub path.
582
     *
583
     * @return string
584
     */
585 3
    public function getStubPath()
586
    {
587 3
        if ($this->stubPath !== null) {
588 1
            return $this->stubPath;
589
        }
590
591 2
        if ($this->config('stubs.enabled') === true) {
592 1
            return $this->config('stubs.path');
593
        }
594
595 1
        return $this->stubPath;
596
    }
597
598
    /**
599
     * Set stub path.
600
     *
601
     * @param string $stubPath
602
     *
603
     * @return $this
604
     */
605 1
    public function setStubPath($stubPath)
606
    {
607 1
        $this->stubPath = $stubPath;
608
609 1
        return $this;
610
    }
611
}
612