Completed
Push — master ( aa54f5...4fafa1 )
by Nicolas
04:04
created

FileRepository::isDisabled()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
cc 1
nc 1
nop 1
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Nwidart\Modules;
4
5
use Countable;
6
use Illuminate\Cache\CacheManager;
7
use Illuminate\Container\Container;
8
use Illuminate\Contracts\Config\Repository as ConfigRepository;
9
use Illuminate\Contracts\Routing\UrlGenerator;
10
use Illuminate\Filesystem\Filesystem;
11
use Illuminate\Support\Str;
12
use Illuminate\Support\Traits\Macroable;
13
use Nwidart\Modules\Contracts\RepositoryInterface;
14
use Nwidart\Modules\Exceptions\InvalidAssetPath;
15
use Nwidart\Modules\Exceptions\ModuleNotFoundException;
16
use Nwidart\Modules\Process\Installer;
17
use Nwidart\Modules\Process\Updater;
18
19
abstract class FileRepository implements RepositoryInterface, Countable
20
{
21
    use Macroable;
22
23
    /**
24
     * Application instance.
25
     *
26
     * @var \Illuminate\Contracts\Foundation\Application|\Laravel\Lumen\Application
27
     */
28
    protected $app;
29
30
    /**
31
     * The module path.
32
     *
33
     * @var string|null
34
     */
35
    protected $path;
36
37
    /**
38
     * The scanned paths.
39
     *
40
     * @var array
41
     */
42
    protected $paths = [];
43
44
    /**
45
     * @var string
46
     */
47
    protected $stubPath;
48
    /**
49
     * @var UrlGenerator
50
     */
51
    private $url;
52
    /**
53
     * @var ConfigRepository
54
     */
55
    private $config;
56
    /**
57
     * @var Filesystem
58
     */
59
    private $files;
60
    /**
61
     * @var CacheManager
62
     */
63
    private $cache;
64
65
    /**
66
     * The constructor.
67
     * @param Container $app
68
     * @param string|null $path
69
     */
70 217
    public function __construct(Container $app, $path = null)
71
    {
72 217
        $this->app = $app;
0 ignored issues
show
Documentation Bug introduced by
It seems like $app of type object<Illuminate\Container\Container> is incompatible with the declared type object<Illuminate\Contra...avel\Lumen\Application> of property $app.

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...
73 217
        $this->path = $path;
74 217
        $this->url = $app['url'];
75 217
        $this->config = $app['config'];
76 217
        $this->files = $app['files'];
77 217
        $this->cache = $app['cache'];
78 217
    }
79
80
    /**
81
     * Add other module location.
82
     *
83
     * @param string $path
84
     *
85
     * @return $this
86
     */
87 15
    public function addLocation($path)
88
    {
89 15
        $this->paths[] = $path;
90
91 15
        return $this;
92
    }
93
94
    /**
95
     * Get all additional paths.
96
     *
97
     * @return array
98
     */
99 1
    public function getPaths() : array
100
    {
101 1
        return $this->paths;
102
    }
103
104
    /**
105
     * Get scanned modules paths.
106
     *
107
     * @return array
108
     */
109 217
    public function getScanPaths() : array
110
    {
111 217
        $paths = $this->paths;
112
113 217
        $paths[] = $this->getPath();
114
115 217
        if ($this->config('scan.enabled')) {
116
            $paths = array_merge($paths, $this->config('scan.paths'));
117
        }
118
119
        $paths = array_map(function ($path) {
120 217
            return Str::endsWith($path, '/*') ? $path : Str::finish($path, '/*');
121 217
        }, $paths);
122
123 217
        return $paths;
124
    }
125
126
    /**
127
     * Creates a new Module instance
128
     *
129
     * @param Container $app
0 ignored issues
show
Bug introduced by
There is no parameter named $app. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
130
     * @param string $args
131
     * @param string $path
0 ignored issues
show
Bug introduced by
There is no parameter named $path. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
132
     * @return \Nwidart\Modules\Module
133
     */
134
    abstract protected function createModule(...$args);
135
136
    /**
137
     * Get & scan all modules.
138
     *
139
     * @return array
140
     */
141 217
    public function scan()
142
    {
143 217
        $paths = $this->getScanPaths();
144
145 217
        $modules = [];
146
147 217
        foreach ($paths as $key => $path) {
148 217
            $manifests = $this->getFiles()->glob("{$path}/module.json");
149
150 217
            is_array($manifests) || $manifests = [];
151
152 217
            foreach ($manifests as $manifest) {
153 133
                $name = Json::make($manifest)->get('name');
154
155 133
                $modules[$name] = $this->createModule($this->app, $name, dirname($manifest));
156
            }
157
        }
158
159 217
        return $modules;
160
    }
161
162
    /**
163
     * Get all modules.
164
     *
165
     * @return array
166
     */
167 217
    public function all() : array
168
    {
169 217
        if (!$this->config('cache.enabled')) {
170 217
            return $this->scan();
171
        }
172
173
        return $this->formatCached($this->getCached());
174
    }
175
176
    /**
177
     * Format the cached data as array of modules.
178
     *
179
     * @param array $cached
180
     *
181
     * @return array
182
     */
183
    protected function formatCached($cached)
184
    {
185
        $modules = [];
186
187
        foreach ($cached as $name => $module) {
188
            $path = $module['path'];
189
190
            $modules[$name] = $this->createModule($this->app, $name, $path);
191
        }
192
193
        return $modules;
194
    }
195
196
    /**
197
     * Get cached modules.
198
     *
199
     * @return array
200
     */
201
    public function getCached()
202
    {
203
        return $this->cache->remember($this->config('cache.key'), $this->config('cache.lifetime'), function () {
204
            return $this->toCollection()->toArray();
205
        });
206
    }
207
208
    /**
209
     * Get all modules as collection instance.
210
     *
211
     * @return Collection
212
     */
213 1
    public function toCollection() : Collection
214
    {
215 1
        return new Collection($this->scan());
216
    }
217
218
    /**
219
     * Get modules by status.
220
     *
221
     * @param $status
222
     *
223
     * @return array
224
     */
225 217
    public function getByStatus($status) : array
226
    {
227 217
        $modules = [];
228
229
        /** @var Module $module */
230 217
        foreach ($this->all() as $name => $module) {
231 3
            if ($module->isStatus($status)) {
232 1
                $modules[$name] = $module;
233
            }
234
        }
235
236 217
        return $modules;
237
    }
238
239
    /**
240
     * Determine whether the given module exist.
241
     *
242
     * @param $name
243
     *
244
     * @return bool
245
     */
246 120
    public function has($name) : bool
247
    {
248 120
        return array_key_exists($name, $this->all());
249
    }
250
251
    /**
252
     * Get list of enabled modules.
253
     *
254
     * @return array
255
     */
256 217
    public function allEnabled() : array
257
    {
258 217
        return $this->getByStatus(true);
259
    }
260
261
    /**
262
     * Get list of disabled modules.
263
     *
264
     * @return array
265
     */
266 1
    public function allDisabled() : array
267
    {
268 1
        return $this->getByStatus(false);
269
    }
270
271
    /**
272
     * Get count from all modules.
273
     *
274
     * @return int
275
     */
276 1
    public function count() : int
277
    {
278 1
        return count($this->all());
279
    }
280
281
    /**
282
     * Get all ordered modules.
283
     *
284
     * @param string $direction
285
     *
286
     * @return array
287
     */
288 217
    public function getOrdered($direction = 'asc') : array
289
    {
290 217
        $modules = $this->allEnabled();
291
292
        uasort($modules, function (Module $a, Module $b) use ($direction) {
293
            if ($a->get('order') === $b->get('order')) {
294
                return 0;
295
            }
296
297
            if ($direction === 'desc') {
298
                return $a->get('order') < $b->get('order') ? 1 : -1;
299
            }
300
301
            return $a->get('order') > $b->get('order') ? 1 : -1;
302 217
        });
303
304 217
        return $modules;
305
    }
306
307
    /**
308
     * @inheritDoc
309
     */
310 217
    public function getPath() : string
311
    {
312 217
        return $this->path ?: $this->config('paths.modules', base_path('Modules'));
313
    }
314
315
    /**
316
     * @inheritDoc
317
     */
318 217
    public function register(): void
319
    {
320 217
        foreach ($this->getOrdered() as $module) {
321
            $module->register();
322
        }
323 217
    }
324
325
    /**
326
     * @inheritDoc
327
     */
328 217
    public function boot(): void
329
    {
330 217
        foreach ($this->getOrdered() as $module) {
331
            $module->boot();
332
        }
333 217
    }
334
335
    /**
336
     * @inheritDoc
337
     */
338 129
    public function find(string $name)
339
    {
340 129
        foreach ($this->all() as $module) {
341 128
            if ($module->getLowerName() === strtolower($name)) {
342 128
                return $module;
343
            }
344
        }
345
346 121
        return;
347
    }
348
349
    /**
350
     * @inheritDoc
351
     */
352 2
    public function findByAlias(string $alias)
353
    {
354 2
        foreach ($this->all() as $module) {
355 2
            if ($module->getAlias() === $alias) {
356 2
                return $module;
357
            }
358
        }
359
360
        return;
361
    }
362
363
    /**
364
     * @inheritDoc
365
     */
366 1
    public function findRequirements($name): array
367
    {
368 1
        $requirements = [];
369
370 1
        $module = $this->findOrFail($name);
371
372 1
        foreach ($module->getRequires() as $requirementName) {
373 1
            $requirements[] = $this->findByAlias($requirementName);
374
        }
375
376 1
        return $requirements;
377
    }
378
379
    /**
380
     * Find a specific module, if there return that, otherwise throw exception.
381
     *
382
     * @param $name
383
     *
384
     * @return Module
385
     *
386
     * @throws ModuleNotFoundException
387
     */
388 127
    public function findOrFail(string $name)
389
    {
390 127
        $module = $this->find($name);
391
392 127
        if ($module !== null) {
393 126
            return $module;
394
        }
395
396 121
        throw new ModuleNotFoundException("Module [{$name}] does not exist!");
397
    }
398
399
    /**
400
     * Get all modules as laravel collection instance.
401
     *
402
     * @param $status
403
     *
404
     * @return Collection
405
     */
406 1
    public function collections($status = 1) : Collection
407
    {
408 1
        return new Collection($this->getByStatus($status));
409
    }
410
411
    /**
412
     * Get module path for a specific module.
413
     *
414
     * @param $module
415
     *
416
     * @return string
417
     */
418 120
    public function getModulePath($module)
419
    {
420
        try {
421 120
            return $this->findOrFail($module)->getPath() . '/';
422 120
        } catch (ModuleNotFoundException $e) {
423 120
            return $this->getPath() . '/' . Str::studly($module) . '/';
424
        }
425
    }
426
427
    /**
428
     * @inheritDoc
429
     */
430 2
    public function assetPath(string $module) : string
431
    {
432 2
        return $this->config('paths.assets') . '/' . $module;
433
    }
434
435
    /**
436
     * @inheritDoc
437
     */
438 217
    public function config(string $key, $default = null)
439
    {
440 217
        return $this->config->get('modules.' . $key, $default);
441
    }
442
443
    /**
444
     * Get storage path for module used.
445
     *
446
     * @return string
447
     */
448 2
    public function getUsedStoragePath() : string
449
    {
450 2
        $directory = storage_path('app/modules');
451 2
        if ($this->getFiles()->exists($directory) === false) {
452 1
            $this->getFiles()->makeDirectory($directory, 0777, true);
453
        }
454
455 2
        $path = storage_path('app/modules/modules.used');
456 2
        if (!$this->getFiles()->exists($path)) {
457 1
            $this->getFiles()->put($path, '');
458
        }
459
460 2
        return $path;
461
    }
462
463
    /**
464
     * Set module used for cli session.
465
     *
466
     * @param $name
467
     *
468
     * @throws ModuleNotFoundException
469
     */
470 1
    public function setUsed($name)
471
    {
472 1
        $module = $this->findOrFail($name);
473
474 1
        $this->getFiles()->put($this->getUsedStoragePath(), $module);
475 1
    }
476
477
    /**
478
     * Forget the module used for cli session.
479
     */
480
    public function forgetUsed()
481
    {
482
        if ($this->getFiles()->exists($this->getUsedStoragePath())) {
483
            $this->getFiles()->delete($this->getUsedStoragePath());
484
        }
485
    }
486
487
    /**
488
     * Get module used for cli session.
489
     * @return string
490
     * @throws \Nwidart\Modules\Exceptions\ModuleNotFoundException
491
     */
492 1
    public function getUsedNow() : string
493
    {
494 1
        return $this->findOrFail($this->getFiles()->get($this->getUsedStoragePath()));
495
    }
496
497
    /**
498
     * Get laravel filesystem instance.
499
     *
500
     * @return Filesystem
501
     */
502 217
    public function getFiles(): Filesystem
503
    {
504 217
        return $this->files;
505
    }
506
507
    /**
508
     * Get module assets path.
509
     *
510
     * @return string
511
     */
512 2
    public function getAssetsPath() : string
513
    {
514 2
        return $this->config('paths.assets');
515
    }
516
517
    /**
518
     * Get asset url from a specific module.
519
     * @param string $asset
520
     * @return string
521
     * @throws InvalidAssetPath
522
     */
523 2
    public function asset($asset) : string
524
    {
525 2
        if (Str::contains($asset, ':') === false) {
526 1
            throw InvalidAssetPath::missingModuleName($asset);
527
        }
528 1
        list($name, $url) = explode(':', $asset);
529
530 1
        $baseUrl = str_replace(public_path() . DIRECTORY_SEPARATOR, '', $this->getAssetsPath());
531
532 1
        $url = $this->url->asset($baseUrl . "/{$name}/" . $url);
533
534 1
        return str_replace(['http://', 'https://'], '//', $url);
535
    }
536
537
    /**
538
     * @inheritDoc
539
     */
540 6
    public function isEnabled(string $name) : bool
541
    {
542 6
        return $this->findOrFail($name)->isEnabled();
543
    }
544
545
    /**
546
     * @inheritDoc
547
     */
548 3
    public function isDisabled(string $name) : bool
549
    {
550 3
        return !$this->isEnabled($name);
551
    }
552
553
    /**
554
     * Enabling a specific module.
555
     * @param string $name
556
     * @return void
557
     * @throws \Nwidart\Modules\Exceptions\ModuleNotFoundException
558
     */
559 2
    public function enable($name)
560
    {
561 2
        $this->findOrFail($name)->enable();
562 2
    }
563
564
    /**
565
     * Disabling a specific module.
566
     * @param string $name
567
     * @return void
568
     * @throws \Nwidart\Modules\Exceptions\ModuleNotFoundException
569
     */
570 1
    public function disable($name)
571
    {
572 1
        $this->findOrFail($name)->disable();
573 1
    }
574
575
    /**
576
     * @inheritDoc
577
     */
578 100
    public function delete($name) : bool
579
    {
580 100
        return $this->findOrFail($name)->delete();
581
    }
582
583
    /**
584
     * Update dependencies for the specified module.
585
     *
586
     * @param string $module
587
     */
588
    public function update($module)
589
    {
590
        with(new Updater($this))->update($module);
591
    }
592
593
    /**
594
     * Install the specified module.
595
     *
596
     * @param string $name
597
     * @param string $version
598
     * @param string $type
599
     * @param bool   $subtree
600
     *
601
     * @return \Symfony\Component\Process\Process
602
     */
603
    public function install($name, $version = 'dev-master', $type = 'composer', $subtree = false)
604
    {
605
        $installer = new Installer($name, $version, $type, $subtree);
606
607
        return $installer->run();
608
    }
609
610
    /**
611
     * Get stub path.
612
     *
613
     * @return string|null
614
     */
615 3
    public function getStubPath()
616
    {
617 3
        if ($this->stubPath !== null) {
618 1
            return $this->stubPath;
619
        }
620
621 2
        if ($this->config('stubs.enabled') === true) {
622 1
            return $this->config('stubs.path');
623
        }
624
625 1
        return $this->stubPath;
626
    }
627
628
    /**
629
     * Set stub path.
630
     *
631
     * @param string $stubPath
632
     *
633
     * @return $this
634
     */
635 1
    public function setStubPath($stubPath)
636
    {
637 1
        $this->stubPath = $stubPath;
638
639 1
        return $this;
640
    }
641
}
642