Code

< 40 %
40-60 %
> 60 %
1
<?php
2
3
namespace Nwidart\Modules;
4
5
use Illuminate\Cache\CacheManager;
6
use Illuminate\Container\Container;
7
use Illuminate\Filesystem\Filesystem;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Str;
10
use Illuminate\Support\Traits\Macroable;
11
use Illuminate\Translation\Translator;
12
use Nwidart\Modules\Contracts\ActivatorInterface;
13
14
abstract class Module
15
{
16
    use Macroable;
17
18
    /**
19
     * The laravel|lumen application instance.
20
     *
21
     * @var \Illuminate\Contracts\Foundation\Application|\Laravel\Lumen\Application
22
     */
23
    protected $app;
24
25
    /**
26
     * The module name.
27
     *
28
     * @var
29
     */
30
    protected $name;
31
32
    /**
33
     * The module path.
34
     *
35
     * @var string
36
     */
37
    protected $path;
38
39
    /**
40
     * @var array of cached Json objects, keyed by filename
41
     */
42
    protected $moduleJson = [];
43
    /**
44
     * @var CacheManager
45
     */
46
    private $cache;
47
    /**
48
     * @var Filesystem
49
     */
50
    private $files;
51
    /**
52
     * @var Translator
53
     */
54
    private $translator;
55
    /**
56
     * @var ActivatorInterface
57
     */
58
    private $activator;
59
60
    /**
61
     * The constructor.
62
     * @param Container $app
63
     * @param $name
64
     * @param $path
65
     */
66 190
    public function __construct(Container $app, string $name, $path)
67
    {
68 190
        $this->name = $name;
69 190
        $this->path = $path;
70 190
        $this->cache = $app['cache'];
71 190
        $this->files = $app['files'];
72 190
        $this->translator = $app['translator'];
73 190
        $this->activator = $app[ActivatorInterface::class];
74 190
        $this->app = $app;
75 190
    }
76
77
    /**
78
     * Returns an array of assets
79
     *
80
     * @return array
81
     */
82 132
    public static function getAssets(): array
83
    {
84 132
        $paths = [];
85
86
        if (file_exists(public_path('build/manifest.json'))) {
87
            $files = json_decode(file_get_contents(public_path('build/manifest.json')), true);
88
89
            if (is_array($files)) {
90
                foreach ($files as $file) {
91
                    // Ignore files which aren't entrypoints.
92 146
                    if (empty($file['isEntry'])) {
93
                        continue;
94 146
                    }
95
96
                    if (isset($file['src'])) {
97
                        $paths[] = $file['src'];
98
                    }
99
                }
100
            }
101
        }
102 131
103
        return $paths;
104 131
    }
105
106
    /**
107
     * Get name.
108
     *
109
     * @return string
110
     */
111
    public function getName(): string
112 6
    {
113
        return $this->name;
114 6
    }
115
116
    /**
117
     * Get name in lower case.
118
     *
119
     * @return string
120
     */
121
    public function getLowerName(): string
122 2
    {
123
        return strtolower($this->name);
124 2
    }
125
126
    /**
127
     * Get name in studly case.
128
     *
129
     * @return string
130
     */
131
    public function getStudlyName(): string
132 4
    {
133
        return Str::studly($this->name);
134 4
    }
135
136
    /**
137
     * Get name in snake case.
138
     *
139
     * @return string
140
     */
141
    public function getSnakeName(): string
142
    {
143
        return Str::snake($this->name);
144
    }
145
146
    /**
147
     * Get description.
148
     *
149
     * @return string
150
     */
151
    public function getDescription(): string
152 3
    {
153
        return $this->get('description');
154 3
    }
155
156
    /**
157
     * Get priority.
158
     *
159
     * @return string
160
     */
161
    public function getPriority(): string
162 152
    {
163
        return $this->get('priority');
164 152
    }
165
166
    /**
167
     * Get path.
168
     *
169
     * @return string
170
     */
171
    public function getPath(): string
172
    {
173
        return $this->path;
174
    }
175
176
    /**
177
     * Get app path.
178
     *
179
     * @return string
180
     */
181
    public function getAppPath(): string
182
    {
183
        $app_path = rtrim($this->getExtraPath(config('modules.paths.app_folder', '')), '/');
184 2
185
        return is_dir($app_path) ? $app_path : $this->getPath();
186 2
    }
187 2
188
    /**
189
     * Set path.
190 2
     *
191
     * @param string $path
192
     *
193
     * @return $this
194 2
     */
195 2
    public function setPath($path): Module
196
    {
197
        $this->path = $path;
198
199
        return $this;
200
    }
201
202 2
    /**
203
     * Bootstrap the application events.
204 2
     */
205
    public function boot(): void
206 2
    {
207
        if (config('modules.register.translations', true) === true) {
208 2
            $this->registerTranslation();
209 2
        }
210
211 2
        if ($this->isLoadFilesOnBoot()) {
212
            $this->registerFiles();
213
        }
214
215
        $this->fireEvent('boot');
216
    }
217
218
    /**
219
     * Register module's translation.
220 124
     *
221
     * @return void
222 124
     */
223 122
    protected function registerTranslation(): void
224
    {
225
        $lowerName = $this->getLowerName();
226
227 124
        $langPath = $this->getPath() . '/Resources/lang';
228 124
229
        if (is_dir($langPath)) {
230
            $this->loadTranslationsFrom($langPath, $lowerName);
231
        }
232
    }
233
234
    /**
235
     * Get json contents from the cache, setting as needed.
236
     *
237
     * @param string $file
238
     *
239 14
     * @return Json
240
     */
241 14
    public function json($file = null): Json
242
    {
243
        if ($file === null) {
244
            $file = 'module.json';
245
        }
246
247
        return Arr::get($this->moduleJson, $file, function () use ($file) {
248
            return $this->moduleJson[$file] = new Json($this->getPath() . '/' . $file, $this->files);
249
        });
250
    }
251
252 2
    /**
253
     * Get a specific data from json file by given the key.
254 2
     *
255
     * @param string $key
256
     * @param null $default
257
     *
258
     * @return mixed
259
     */
260
    public function get(string $key, $default = null)
261
    {
262
        return $this->json()->get($key, $default);
263
    }
264
265
    /**
266
     * Get a specific data from composer.json file by given the key.
267
     *
268
     * @param $key
269
     * @param null $default
270
     *
271
     * @return mixed
272
     */
273
    public function getComposerAttr($key, $default = null)
274
    {
275
        return $this->json('composer.json')->get($key, $default);
276
    }
277
278 11
    /**
279
     * Register the module.
280 11
     */
281 11
    public function register(): void
282
    {
283
        $this->registerAliases();
284
285
        $this->registerProviders();
286
287
        if ($this->isLoadFilesOnBoot() === false) {
288
            $this->registerFiles();
289
        }
290
291
        $this->fireEvent('register');
292
    }
293
294
    /**
295
     * Register the module event.
296
     *
297
     * @param string $event
298
     */
299
    protected function fireEvent($event): void
300
    {
301
        $this->app['events']->dispatch(sprintf('modules.%s.' . $event, $this->getLowerName()), [$this]);
302
    }
303
304
    /**
305
     * Register the aliases from this module.
306
     */
307
    abstract public function registerAliases(): void;
308
309
    /**
310
     * Register the service providers from this module.
311
     */
312
    abstract public function registerProviders(): void;
313
314 5
    /**
315
     * Get the path to the cached *_module.php file.
316 5
     *
317
     * @return string
318
     */
319
    abstract public function getCachedServicesPath(): string;
320
321
    /**
322
     * Register the files from this module.
323
     */
324
    protected function registerFiles(): void
325
    {
326 5
        foreach ($this->get('files', []) as $file) {
327
            include $this->path . '/' . $file;
328 5
        }
329
    }
330
331
    /**
332
     * Handle call __toString.
333
     *
334
     * @return string
335
     */
336 12
    public function __toString()
337
    {
338 12
        return $this->getStudlyName();
339
    }
340
341
    /**
342
     * Determine whether the given status same with the current module status.
343
     *
344
     * @param bool $status
345
     *
346 4
     * @return bool
347
     */
348 4
    public function isStatus(bool $status): bool
349
    {
350
        return $this->activator->hasStatus($this, $status);
351
    }
352
353
    /**
354
     * Determine whether the current module activated.
355
     *
356
     * @return bool
357
     */
358 1
    public function isEnabled(): bool
359
    {
360 1
        return $this->activator->hasStatus($this, true);
361 1
    }
362
363
    /**
364
     *  Determine whether the current module not disabled.
365
     *
366 5
     * @return bool
367
     */
368 5
    public function isDisabled(): bool
369
    {
370 5
        return !$this->isEnabled();
371 5
    }
372
373 5
    /**
374 5
     * Set active state for current module.
375
     *
376
     * @param bool $active
377
     *
378
     * @return void
379 6
     */
380
    public function setActive(bool $active): void
381 6
    {
382
        $this->activator->setActive($this, $active);
383 6
    }
384 6
385
    /**
386 6
     * Disable the current module.
387 6
     */
388
    public function disable(): void
389
    {
390
        $this->fireEvent('disabling');
391
392
        $this->activator->disable($this);
393
        $this->flushCache();
394 107
395
        $this->fireEvent('disabled');
396 107
    }
397
398 107
    /**
399
     * Enable the current module.
400
     */
401
    public function enable(): void
402
    {
403
        $this->fireEvent('enabling');
404
405
        $this->activator->enable($this);
406
        $this->flushCache();
407
408 3
        $this->fireEvent('enabled');
409
    }
410 3
411
    /**
412
     * Delete the current module.
413
     *
414
     * @return bool
415
     */
416
    public function delete(): bool
417
    {
418 2
        $this->activator->delete($this);
419
420 2
        return $this->json()->getFilesystem()->deleteDirectory($this->getPath());
421
    }
422 2
423
    /**
424
     * Get extra path.
425 9
     *
426
     * @param string $path
427 9
     *
428
     * @return string
429
     */
430 9
    public function getExtraPath(string $path): string
431
    {
432
        return $this->getPath() . '/' . $path;
433
    }
434
435
    /**
436
     * Check if can load files of module on boot method.
437
     *
438
     * @return bool
439 2
     */
440
    protected function isLoadFilesOnBoot(): bool
441 2
    {
442 2
        return config('modules.register.files', 'register') === 'boot' &&
443
            // force register method if option == boot && app is AsgardCms
444
            !class_exists('\Modules\Core\Foundation\AsgardCms');
445
    }
446
447
    private function flushCache(): void
448
    {
449
        if (config('modules.cache.enabled')) {
450
            $this->cache->store(config('modules.cache.driver'))->flush();
451
        }
452
    }
453
454
    /**
455
     * Register a translation file namespace.
456
     *
457
     * @param  string  $path
458
     * @param  string  $namespace
459
     * @return void
460
     */
461
    private function loadTranslationsFrom(string $path, string $namespace): void
462
    {
463
        $this->translator->addNamespace($namespace, $path);
464
    }
465
}
466