Completed
Push — master ( b0653b...b88c60 )
by Nicolas
05:50
created

Repository::getScanPaths()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0932

Importance

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