GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Modules::getActiveModule()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * This file is part of the O2System Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
12
// ------------------------------------------------------------------------
13
14
namespace O2System\Framework\Containers;
15
16
// ------------------------------------------------------------------------
17
18
use O2System\Cache\Item;
19
use O2System\Framework\Containers\Modules\DataStructures;
20
use O2System\Framework\Services\Hooks;
21
use O2System\Kernel\Cli\Writers\Format;
22
use O2System\Kernel\Http\Router\Addresses;
23
use O2System\Spl\DataStructures\SplArrayStack;
24
use O2System\Spl\Info\SplNamespaceInfo;
25
use Psr\Cache\CacheItemPoolInterface;
26
27
/**
28
 * Class Modules
29
 *
30
 * @package O2System\Framework\Containers
31
 */
32
class Modules extends SplArrayStack
33
{
34
    /**
35
     * Modules::$types
36
     *
37
     * List of module types.
38
     *
39
     * @var array
40
     */
41
    private $types = [
42
        'apps',
43
        'modules',
44
        'components',
45
        'plugins',
46
    ];
47
48
    /**
49
     * Modules::$registry
50
     *
51
     * Modules registries.
52
     *
53
     * @var array
54
     */
55
    private $registry = [];
56
57
    /**
58
     * Modules::loaded
59
     *
60
     * @var array
61
     */
62
    private $loaded = [];
63
64
    /**
65
     * Modules::$activeApp
66
     *
67
     * @var \O2System\Framework\Containers\Modules\DataStructures\Module
68
     */
69
    private $activeApp;
70
71
    /**
72
     * Modules::$activeModule
73
     *
74
     * @var \O2System\Framework\Containers\Modules\DataStructures\Module
75
     */
76
    private $activeModule;
77
78
    // ------------------------------------------------------------------------
79
80
    /**
81
     * Modules::__construct
82
     */
83
    public function __construct()
84
    {
85
        parent::__construct();
86
87
        // Autoload Main Modularity: Kernel, Framework and App
88
        $kernel = (new DataStructures\Module(PATH_KERNEL))
89
            ->setType('KERNEL')
90
            ->setNamespace('O2System\Kernel\\');
91
92
        $this->autoload($kernel);
93
        parent::push($kernel);
94
95
        $framework = (new DataStructures\Module(PATH_FRAMEWORK))
96
            ->setType('FRAMEWORK')
97
            ->setNamespace('O2System\Framework\\');
98
99
        $this->autoload($framework);
100
        parent::push($framework);
101
102
        $app = (new DataStructures\Module(PATH_APP))
103
            ->setType('APP')
104
            ->setNamespace('App\\');
105
        $this->activeApp = $app;
106
107
        $this->autoload($app);
108
        parent::push($app);
109
    }
110
111
    // ------------------------------------------------------------------------
112
113
    /**
114
     * Modules::autoload
115
     *
116
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
117
     */
118
    private function autoload(DataStructures\Module $module)
119
    {
120
        if ( ! in_array($module->getRealPath(), $this->loaded)) {
121
            // Register to loaded property
122
            $this->loaded[] = $module->getRealPath();
123
124
            // Register Framework\Services\Loader Namespace
125
            loader()->addNamespace($module->getNamespace(), $module->getRealPath());
126
127
            $this->autoloadHelpers($module);
128
129
            if ( ! in_array($module->getType(), ['KERNEL', 'FRAMEWORK'])) {
130
131
                // Autoload Module Language
132
                language()
133
                    ->addFilePath($module->getRealPath())
134
                    ->loadFile(dash($module->getParameter()));
135
136
                // Autoload Module Config
137
                $this->autoloadConfig($module);
138
139
                // Autoload Module Addresses
140
                $this->autoloadAddresses($module);
141
142
                // Autoload Module Hooks Closures
143
                $this->autoloadHooks($module);
144
145
                // Autoload Module Models
146
                $this->autoloadModels($module);
147
148
                // Autoload Services Models
149
                $this->autoloadServices($module);
150
            }
151
        }
152
153
    }
154
155
    // ------------------------------------------------------------------------
156
157
    /**
158
     * Modules::autoloadHelpers
159
     *
160
     * Autoload modules helpers.
161
     *
162
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
163
     */
164
    private function autoloadHelpers(DataStructures\Module $module)
165
    {
166
        loader()->loadHelper(studlycase($module->getParameter()));
167
168
        if (is_file(
169
            $filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . ucfirst(
170
                    strtolower(ENVIRONMENT)
0 ignored issues
show
Bug introduced by
The constant O2System\Framework\Containers\ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
171
                ) . DIRECTORY_SEPARATOR . 'Helpers.php'
172
        )) {
173
            include($filePath);
174
        } elseif (is_file($filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . 'Helpers.php')) {
175
            include($filePath);
176
        }
177
178
        if (isset($helpers) AND is_array($helpers)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $helpers seems to never exist and therefore isset should always be false.
Loading history...
179
            loader()->loadHelpers($helpers);
180
        }
181
    }
182
183
    // ------------------------------------------------------------------------
184
185
    /**
186
     * Modules::autoloadConfig
187
     *
188
     * Autoload modules config.
189
     *
190
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
191
     */
192
    private function autoloadConfig(DataStructures\Module $module)
193
    {
194
        if (is_file(
195
            $filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . ucfirst(
196
                    strtolower(ENVIRONMENT)
0 ignored issues
show
Bug introduced by
The constant O2System\Framework\Containers\ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
197
                ) . DIRECTORY_SEPARATOR . 'Config.php'
198
        )) {
199
            include($filePath);
200
        } elseif (is_file($filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . 'Config.php')) {
201
            include($filePath);
202
        }
203
204
        if (isset($config) AND is_array($config)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $config seems to never exist and therefore isset should always be false.
Loading history...
205
            // Set default timezone
206
            if (isset($config[ 'datetime' ][ 'timezone' ])) {
207
                date_default_timezone_set($config[ 'datetime' ][ 'timezone' ]);
208
            }
209
210
            // Setup Language Ideom and Locale
211
            if (isset($config[ 'language' ])) {
212
                language()->setDefault($config[ 'language' ]);
213
            }
214
215
            config()->merge($config);
216
217
            unset($config);
218
        }
219
    }
220
221
    // ------------------------------------------------------------------------
222
223
    /**
224
     * Modules::autoloadAddresses
225
     *
226
     * Autoload modules routes.
227
     *
228
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
229
     */
230
    private function autoloadAddresses(DataStructures\Module $module)
231
    {
232
        // Routes is not available on cli
233
        if (is_cli()) {
234
            return;
235
        }
236
237
        if (is_file(
238
            $filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . ucfirst(
239
                    strtolower(ENVIRONMENT)
0 ignored issues
show
Bug introduced by
The constant O2System\Framework\Containers\ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
240
                ) . DIRECTORY_SEPARATOR . 'Addresses.php'
241
        )) {
242
            include($filePath);
243
        } elseif (is_file($filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . 'Addresses.php')) {
244
            include($filePath);
245
        }
246
247
        if (isset($addresses) AND $addresses instanceof Addresses) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $addresses seems to never exist and therefore isset should always be false.
Loading history...
248
            config()->addItem('addresses', $addresses);
0 ignored issues
show
Bug introduced by
The method addItem() does not exist on O2System\Kernel\DataStructures\Config. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

248
            config()->/** @scrutinizer ignore-call */ addItem('addresses', $addresses);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
249
250
            unset($addresses);
251
        }
252
    }
253
254
    // ------------------------------------------------------------------------
255
256
    /**
257
     * Modules::autoloadHooks
258
     *
259
     * Autoload modules hooks.
260
     *
261
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
262
     */
263
    private function autoloadHooks(DataStructures\Module $module)
264
    {
265
        if (is_file(
266
            $filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . ucfirst(
267
                    strtolower(ENVIRONMENT)
0 ignored issues
show
Bug introduced by
The constant O2System\Framework\Containers\ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
268
                ) . DIRECTORY_SEPARATOR . 'Hooks.php'
269
        )) {
270
            include($filePath);
271
        } elseif (is_file($filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . 'Hooks.php')) {
272
            include($filePath);
273
        }
274
275
        if (isset($hooks) AND is_array($hooks)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hooks seems to never exist and therefore isset should always be false.
Loading history...
276
            foreach ($hooks as $event => $closures) {
277
                if ($event === Hooks::PRE_SYSTEM) {
278
                    // not supported
279
                    continue;
280
                }
281
282
                if (is_array($closures)) {
283
                    foreach ($closures as $closure) {
284
                        hooks()->addClosure($closure, $event);
0 ignored issues
show
Bug introduced by
The method addClosure() does not exist on O2System\Framework\Services\Hooks. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

284
                        hooks()->/** @scrutinizer ignore-call */ addClosure($closure, $event);
Loading history...
285
                    }
286
                } elseif ($closures instanceof \Closure) {
287
                    hooks()->addClosure($closures, $event);
288
                }
289
            }
290
291
            unset($hooks);
292
        }
293
    }
294
295
    // ------------------------------------------------------------------------
296
297
    /**
298
     * Modules::autoloadModels
299
     *
300
     * Autoload modules models.
301
     *
302
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
303
     */
304
    private function autoloadModels(DataStructures\Module $module)
305
    {
306
        if (is_file(
307
            $filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . ucfirst(
308
                    strtolower(ENVIRONMENT)
0 ignored issues
show
Bug introduced by
The constant O2System\Framework\Containers\ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
309
                ) . DIRECTORY_SEPARATOR . 'Models.php'
310
        )) {
311
            include($filePath);
312
        } elseif (is_file($filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . 'Models.php')) {
313
            include($filePath);
314
        }
315
316
        if (isset($models) AND is_array($models)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $models seems to never exist and therefore isset should always be false.
Loading history...
317
            foreach ($models as $offset => $model) {
318
                if (is_string($model)) {
319
                    models()->load($model, $offset);
0 ignored issues
show
Bug introduced by
The method load() does not exist on O2System\Framework\Models\Sql\Model. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

319
                    models()->/** @scrutinizer ignore-call */ load($model, $offset);
Loading history...
Bug introduced by
The method load() does not exist on O2System\Framework\Models\NoSql\Model. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

319
                    models()->/** @scrutinizer ignore-call */ load($model, $offset);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
320
                } elseif (is_object($model)) {
321
                    models()->add($model);
0 ignored issues
show
Bug introduced by
The method add() does not exist on O2System\Framework\Models\NoSql\Model. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

321
                    models()->/** @scrutinizer ignore-call */ add($model);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method add() does not exist on O2System\Framework\Models\Sql\Model. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

321
                    models()->/** @scrutinizer ignore-call */ add($model);
Loading history...
322
                }
323
            }
324
325
            unset($models);
326
        }
327
    }
328
329
    // ------------------------------------------------------------------------
330
331
    /**
332
     * Modules::autoloadServices
333
     *
334
     * Autoload modules services.
335
     *
336
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
337
     */
338
    private function autoloadServices(DataStructures\Module $module)
339
    {
340
        if (is_file(
341
            $filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . ucfirst(
342
                    strtolower(ENVIRONMENT)
0 ignored issues
show
Bug introduced by
The constant O2System\Framework\Containers\ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
343
                ) . DIRECTORY_SEPARATOR . 'Services.php'
344
        )) {
345
            include($filePath);
346
        } elseif (is_file($filePath = $module->getRealPath() . 'Config' . DIRECTORY_SEPARATOR . 'Services.php')) {
347
            include($filePath);
348
        }
349
350
        if (isset($services) AND is_array($services)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $services seems to never exist and therefore isset should always be false.
Loading history...
351
            foreach ($services as $offset => $service) {
352
                if (is_string($service)) {
353
                    services()->load($service, $offset);
354
                } elseif (is_object($service)) {
355
                    services()->add($service);
356
                }
357
            }
358
359
            unset($services);
360
        }
361
    }
362
363
    // ------------------------------------------------------------------------
364
365
    /**
366
     * Modules::push
367
     *
368
     * Replacement of SplArrayStack push method.
369
     *
370
     * @param mixed $module
371
     */
372
    public function push($module)
373
    {
374
        if ( ! in_array($module->getNamespace(), ['O2System\Kernel\\', 'O2System\Framework\\', 'App\\'])) {
375
            if($module instanceof DataStructures\Module) {
376
                $this->autoload($module);
377
378
                parent::push($module);
379
380
                if($module->getType() === 'APP') {
381
                    $this->setActiveApp($module);
382
                } elseif(in_array($module->getType(), ['MODULE', 'COMPONENT'])) {
383
                    $this->setActiveModule($module);
384
                }
385
            }
386
        }
387
    }
388
389
    // ------------------------------------------------------------------------
390
391
    /**
392
     * Modules::loadRegistry
393
     *
394
     * Load modules registry
395
     *
396
     * @return void
397
     * @throws \Psr\Cache\InvalidArgumentException
398
     */
399
    public function loadRegistry()
400
    {
401
        if (empty($this->registry)) {
402
            $cacheItemPool = cache()->getItemPool('default');
403
404
            if (cache()->hasItemPool('registry')) {
405
                $cacheItemPool = cache()->getItemPool('registry');
406
            }
407
408
            if ($cacheItemPool instanceof CacheItemPoolInterface) {
409
                if ($cacheItemPool->hasItem('o2modules')) {
410
                    if ($registry = $cacheItemPool->getItem('o2modules')->get()) {
411
                        $this->registry = $registry;
412
                    } else {
413
                        $this->registry = $this->fetchRegistry();
414
                        $cacheItemPool->save(new Item('o2modules', $this->registry, false));
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type DateInterval|integer expected by parameter $expiresAfter of O2System\Cache\Item::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

414
                        $cacheItemPool->save(new Item('o2modules', $this->registry, /** @scrutinizer ignore-type */ false));
Loading history...
415
                    }
416
                } else {
417
                    $this->registry = $this->fetchRegistry();
418
                    $cacheItemPool->save(new Item('o2modules', $this->registry, false));
419
                }
420
            } else {
421
                $this->registry = $this->fetchRegistry();
422
            }
423
        }
424
    }
425
426
    // ------------------------------------------------------------------------
427
428
    /**
429
     * Modules::fetchRegistry
430
     *
431
     * Fetch modules registry.
432
     *
433
     * @return array
434
     */
435
    public function fetchRegistry()
436
    {
437
        $registry = [];
438
        $directory = new \RecursiveIteratorIterator(
439
            new \RecursiveDirectoryIterator(PATH_APP),
440
            \RecursiveIteratorIterator::SELF_FIRST
441
        );
442
443
        $packagesIterator = new \RegexIterator($directory, '/^.+\.json/i', \RecursiveRegexIterator::GET_MATCH);
444
445
        foreach ($packagesIterator as $packageJsonFiles) {
446
            foreach ($packageJsonFiles as $packageJsonFile) {
447
                $packageJsonFile = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $packageJsonFile);
448
                $packageJsonFileInfo = pathinfo($packageJsonFile);
449
450
                if ($packageJsonFileInfo[ 'filename' ] === 'widget' or
451
                    $packageJsonFileInfo[ 'filename' ] === 'language' or
452
                    strpos($packageJsonFile, '.svn') !== false // subversion properties file conflict.
453
                ) {
454
                    continue;
455
                }
456
457
                if (is_cli()) {
458
                    output()->verbose(
0 ignored issues
show
Bug introduced by
The method verbose() does not exist on O2System\Kernel\Http\Output. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

458
                    output()->/** @scrutinizer ignore-call */ verbose(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
459
                        (new Format())
460
                            ->setString(language()->getLine('CLI_REGISTRY_MODULE_VERB_FETCH_MANIFEST_START',
461
                                [str_replace(PATH_ROOT, '/', $packageJsonFile)]))
0 ignored issues
show
Bug introduced by
The constant O2System\Framework\Containers\PATH_ROOT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
462
                            ->setNewLinesAfter(1)
463
                    );
464
                }
465
466
                $packageJsonMetadata = json_decode(file_get_contents($packageJsonFile), true);
467
468
                if (json_last_error() !== JSON_ERROR_NONE and is_cli()) {
469
                    output()->verbose(
470
                        (new Format())
471
                            ->setContextualClass(Format::DANGER)
472
                            ->setString(language()->getLine('CLI_REGISTRY_MODULE_VERB_FETCH_MANIFEST_FAILED'))
473
                            ->setIndent(2)
474
                            ->setNewLinesAfter(1)
475
                    );
476
                } elseif ( ! is_array($packageJsonMetadata)) {
477
                    continue;
478
                }
479
480
                if (strpos($packageJsonFile,
481
                        $modularType = ucfirst(plural($packageJsonFileInfo[ 'filename' ])) . DIRECTORY_SEPARATOR) === false) {
482
                    $modularType = ucfirst($packageJsonFileInfo[ 'filename' ]) . DIRECTORY_SEPARATOR;
483
                }
484
485
                $modularType = strtolower(rtrim($modularType, DIRECTORY_SEPARATOR));
486
                $this->addType($modularType);
487
488
                $moduleSegments = explode(
489
                    DIRECTORY_SEPARATOR,
490
                    trim(
491
                        str_replace(
492
                            [
493
                                PATH_FRAMEWORK,
494
                                PATH_PUBLIC,
495
                                PATH_RESOURCES,
496
                                PATH_APP,
497
                                $packageJsonFileInfo[ 'basename' ],
498
                            ],
499
                            '',
500
                            $packageJsonFile
501
                        ),
502
                        DIRECTORY_SEPARATOR
503
                    )
504
                );
505
506
                $moduleSegments = array_map(function ($string) {
507
                    return dash(snakecase($string));
508
                }, $moduleSegments);
509
510
                $moduleParentSegments = [];
511
512
                foreach ([
513
                             'apps',
514
                             'modules',
515
                             'components',
516
                             'plugins',
517
                         ] as $moduleType
518
                ) {
519
                    if (false !== ($segmentKey = array_search($modularType, $moduleSegments))) {
520
                        $moduleParentSegments = array_slice($moduleSegments, 0, $segmentKey);
0 ignored issues
show
Bug introduced by
It seems like $segmentKey can also be of type string; however, parameter $length of array_slice() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

520
                        $moduleParentSegments = array_slice($moduleSegments, 0, /** @scrutinizer ignore-type */ $segmentKey);
Loading history...
521
522
                        unset($moduleSegments[ $segmentKey ]);
523
                        break;
524
                    }
525
                }
526
527
                $moduleSegments = array_values($moduleSegments);
528
529
                $moduleNamespace = prepare_namespace(
530
                    str_replace(
531
                        PATH_ROOT,
532
                        '',
533
                        $packageJsonFileInfo[ 'dirname' ]
534
                    ),
535
                    false
536
                );
537
538
                if (isset($packageJsonMetadata[ 'namespace' ])) {
539
                    $moduleNamespace = $packageJsonMetadata[ 'namespace' ];
540
                    unset($packageJsonMetadata[ 'namespace' ]);
541
                }
542
543
                $registryKey = implode('/', $moduleSegments);
544
545
                if ($registryKey === '') {
546
                    if ($packageJsonFileInfo[ 'dirname' ] . DIRECTORY_SEPARATOR !== PATH_APP and $modularType === 'app') {
547
                        $registryKey = dash(snakecase(
548
                            pathinfo($packageJsonFileInfo[ 'dirname' ], PATHINFO_FILENAME)));
549
                    }
550
                }
551
552
                $registry[ $registryKey ] = (new DataStructures\Module(
553
                    $packageJsonFileInfo[ 'dirname' ]
554
                ))
555
                    ->setType($packageJsonFileInfo[ 'filename' ])
556
                    ->setNamespace($moduleNamespace)
557
                    ->setSegments($moduleSegments)
558
                    ->setParentSegments($moduleParentSegments)
559
                    ->setProperties($packageJsonMetadata);
560
561
                if (is_cli()) {
562
                    output()->verbose(
563
                        (new Format())
564
                            ->setContextualClass(Format::SUCCESS)
565
                            ->setString(language()->getLine('CLI_REGISTRY_MODULE_VERB_FETCH_MANIFEST_SUCCESS'))
566
                            ->setIndent(2)
567
                            ->setNewLinesAfter(1)
568
                    );
569
                }
570
            }
571
        }
572
573
        //ksort($registry);
574
575
        return $registry;
576
    }
577
578
    // ------------------------------------------------------------------------
579
580
    /**
581
     * Modules::addType
582
     *
583
     * Add module type.
584
     *
585
     * @param string $type
586
     *
587
     * @return string
588
     */
589
    public function addType($type)
590
    {
591
        $pluralTypes = plural(strtolower($type));
592
593
        if ( ! in_array($pluralTypes, $this->types)) {
594
            array_push($this->types, $pluralTypes);
595
        }
596
597
        return $pluralTypes;
598
    }
599
600
    // ------------------------------------------------------------------------
601
602
    /**
603
     * Modules::getRegistry
604
     *
605
     * Gets modules registries.
606
     *
607
     * @return array
608
     */
609
    public function getRegistry()
610
    {
611
        return $this->registry;
612
    }
613
614
    // ------------------------------------------------------------------------
615
616
    /**
617
     * Modules::getTotalRegistry
618
     *
619
     * Gets total module registry.
620
     *
621
     * @return int
622
     */
623
    public function getTotalRegistry()
624
    {
625
        return count($this->registry);
626
    }
627
628
    // ------------------------------------------------------------------------
629
630
    /**
631
     * Modules::updateRegistry
632
     *
633
     * Update module registry
634
     *
635
     * @return void
636
     * @throws \Exception
637
     */
638
    public function updateRegistry()
639
    {
640
        if (is_cli()) {
641
            output()->verbose(
642
                (new Format())
643
                    ->setContextualClass(Format::WARNING)
644
                    ->setString(language()->getLine('CLI_REGISTRY_MODULE_VERB_UPDATE_START'))
645
                    ->setNewLinesBefore(1)
646
                    ->setNewLinesAfter(2)
647
            );
648
        }
649
650
        $cacheItemPool = cache()->getObject('default');
651
652
        if (cache()->hasItemPool('registry')) {
653
            $cacheItemPool = cache()->getObject('registry');
654
        }
655
656
        if ($cacheItemPool instanceof CacheItemPoolInterface) {
657
            $this->registry = $this->fetchRegistry();
658
            $cacheItemPool->save(new Item('o2modules', $this->registry, false));
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type DateInterval|integer expected by parameter $expiresAfter of O2System\Cache\Item::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

658
            $cacheItemPool->save(new Item('o2modules', $this->registry, /** @scrutinizer ignore-type */ false));
Loading history...
659
        }
660
661
        if (count($this->registry) and is_cli()) {
662
            output()->verbose(
663
                (new Format())
664
                    ->setContextualClass(Format::SUCCESS)
665
                    ->setString(language()->getLine('CLI_REGISTRY_MODULE_VERB_UPDATE_SUCCESS'))
666
                    ->setNewLinesBefore(1)
667
                    ->setNewLinesAfter(2)
668
            );
669
        } elseif (is_cli()) {
670
            output()->verbose(
671
                (new Format())
672
                    ->setContextualClass(Format::DANGER)
673
                    ->setString(language()->getLine('CLI_REGISTRY_MODULE_VERB_UPDATE_FAILED'))
674
                    ->setNewLinesBefore(1)
675
                    ->setNewLinesAfter(2)
676
            );
677
        }
678
    }
679
680
    // ------------------------------------------------------------------------
681
682
    /**
683
     * Modules::flushRegistry
684
     *
685
     * Flush modules registry.
686
     *
687
     * @return void
688
     * @throws \Psr\Cache\InvalidArgumentException
689
     */
690
    public function flushRegistry()
691
    {
692
        $cacheItemPool = cache()->getObject('default');
693
694
        if (cache()->hasItemPool('registry')) {
695
            $cacheItemPool = cache()->getObject('registry');
696
        }
697
698
        if ($cacheItemPool instanceof CacheItemPoolInterface) {
699
            $cacheItemPool->deleteItem('o2modules');
700
        }
701
    }
702
703
    // ------------------------------------------------------------------------
704
705
    /**
706
     * Modules::getApp
707
     *
708
     * @param string $segment
709
     *
710
     * @return bool|DataStructures\Module
711
     */
712
    public function getApp($segment)
713
    {
714
        $segment = dash($segment);
715
716
        if ($this->exists($segment)) {
717
            if ($this->registry[ $segment ] instanceof DataStructures\Module) {
718
                return $this->registry[ $segment ];
719
            }
720
        }
721
722
        return false;
723
    }
724
725
    // ------------------------------------------------------------------------
726
727
    /**
728
     * Modules::isExists
729
     *
730
     * @param string|array $segments
731
     *
732
     * @return bool
733
     */
734
    public function exists($segments)
735
    {
736
        $segments = is_array($segments) ? implode('/', $segments) : $segments;
737
738
        if (is_string($segments)) {
0 ignored issues
show
introduced by
The condition is_string($segments) is always true.
Loading history...
739
            return (bool)array_key_exists($segments, $this->registry);
740
        }
741
742
        return false;
743
    }
744
745
    // ------------------------------------------------------------------------
746
747
    /**
748
     * Modules::first
749
     *
750
     * @return bool|mixed
751
     */
752
    public function first()
753
    {
754
        if (isset($this->registry[ '' ])) {
755
            return $this->registry[ '' ];
756
        } elseif (reset($this->registry)->type === 'APP') {
757
            return reset($this->registry);
758
        }
759
760
        return false;
761
    }
762
763
    // ------------------------------------------------------------------------
764
765
    /**
766
     * Modules::getModule
767
     *
768
     * @param string|array $segments
769
     *
770
     * @return bool|DataStructures\Module
771
     */
772
    public function getModule($segments)
773
    {
774
        $segments = (is_array($segments) ? implode('/', array_map('dash', $segments)) : $segments);
775
776
        if ($this->exists($segments)) {
777
            return $this->registry[ $segments ];
778
        }
779
780
        return false;
781
    }
782
783
    // ------------------------------------------------------------------------
784
785
    /**
786
     * Modules::getNamespaces
787
     *
788
     * Gets module namespaces.
789
     *
790
     * @return array
791
     */
792
    public function getNamespaces()
793
    {
794
        $namespaces = [];
795
796
        foreach ($this as $key => $module) {
797
            if ($module instanceof DataStructures\Module) {
798
                $namespaces[ $key ] = new SplNamespaceInfo($module->getNamespace(), $module->getRealPath());
799
            }
800
        }
801
802
        return $namespaces;
803
    }
804
805
    // ------------------------------------------------------------------------
806
807
    /**
808
     * Modules::getDirs
809
     *
810
     * Gets module directories
811
     *
812
     * @param string $subDir
813
     * @param bool   $reverse
814
     *
815
     * @return array
816
     */
817
    public function getDirs($subDir, $reverse = false)
818
    {
819
        $dirs = [];
820
        $subDir = prepare_class_name($subDir);
821
        $subDir = str_replace(
822
            ['\\', '/'],
823
            DIRECTORY_SEPARATOR,
824
            $subDir
825
        );
826
827
        foreach ($this as $module) {
828
            if ($module instanceof DataStructures\Module) {
829
                if (is_dir($dirPath = $module->getRealPath() . $subDir)) {
830
                    $dirs[] = $dirPath . DIRECTORY_SEPARATOR;
831
                }
832
833
                if (is_dir($dirPath = $module->getRealPath() . (is_cli() ? 'Cli' : 'Http') . DIRECTORY_SEPARATOR . $subDir)) {
834
                    $dirs[] = $dirPath . DIRECTORY_SEPARATOR;
835
                }
836
            }
837
        }
838
839
        return $reverse === true ? array_reverse($dirs) : $dirs;
840
    }
841
842
    // ------------------------------------------------------------------------
843
844
    /**
845
     * Modules::getResourcesDirs
846
     *
847
     * Gets module resources directories
848
     *
849
     * @param string $subDir
850
     * @param bool   $reverse
851
     *
852
     * @return array
853
     */
854
    public function getResourcesDirs($subDir, $reverse = false)
855
    {
856
        $dirs = [];
857
        $subDir = dash($subDir);
858
        $subDir = str_replace(
859
            ['\\', '/'],
860
            DIRECTORY_SEPARATOR,
861
            $subDir
862
        );
863
864
        foreach ($this as $module) {
865
            if ($module instanceof DataStructures\Module) {
866
                if (is_dir($dirPath = $module->getResourcesDir($subDir))) {
0 ignored issues
show
Bug introduced by
It seems like $dirPath = $module->getResourcesDir($subDir) can also be of type false; however, parameter $filename of is_dir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

866
                if (is_dir(/** @scrutinizer ignore-type */ $dirPath = $module->getResourcesDir($subDir))) {
Loading history...
867
                    $dirs[] = $dirPath;
868
                }
869
            }
870
        }
871
872
        return $reverse === true ? array_reverse($dirs) : $dirs;
873
    }
874
875
    // ------------------------------------------------------------------------
876
877
    /**
878
     * Modules::setActiveApp
879
     *
880
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $app
881
     *
882
     * @return static
883
     */
884
    public function setActiveApp(DataStructures\Module $app)
885
    {
886
        $this->activeApp = $app;
887
888
        return $this;
889
    }
890
891
    // ------------------------------------------------------------------------
892
893
    /**
894
     * Modules::setActiveApp
895
     *
896
     * @return \O2System\Framework\Containers\Modules\DataStructures\Module
897
     */
898
    public function getActiveApp()
899
    {
900
        return $this->activeApp;
901
    }
902
903
    // ------------------------------------------------------------------------
904
905
    /**
906
     * Modules::setActiveModule
907
     *
908
     * @param \O2System\Framework\Containers\Modules\DataStructures\Module $module
909
     *
910
     * @return static
911
     */
912
    public function setActiveModule(DataStructures\Module $module)
913
    {
914
        $this->activeModule = $module;
915
916
        return $this;
917
    }
918
919
    // ------------------------------------------------------------------------
920
921
    /**
922
     * Modules::setActiveModule
923
     *
924
     * @return \O2System\Framework\Containers\Modules\DataStructures\Module
925
     */
926
    public function getActiveModule()
927
    {
928
        return $this->activeModule;
929
    }
930
}