Completed
Pull Request — master (#214)
by Nauris
11:52
created

Repository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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