Passed
Push — master ( 9c811f...1ee935 )
by Attila
03:55
created

BaseServiceProvider::boot()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 24
rs 9.4888
cc 5
nc 16
nop 0
1
<?php
2
/**
3
 * Contains the BaseServiceProvider class.
4
 *
5
 * @copyright   Copyright (c) 2016 Attila Fulop
6
 * @author      Attila Fulop
7
 * @license     MIT
8
 * @since       2016-12-29
9
 *
10
 */
11
12
namespace Konekt\Concord;
13
14
use Illuminate\Support\ServiceProvider;
15
use Konekt\Concord\Contracts\Concord as ConcordContract;
16
use Konekt\Concord\Contracts\Convention;
17
use Konekt\Concord\Contracts\Module;
18
use Konekt\Concord\Module\Manifest;
19
use Konekt\Concord\Module\Kind;
20
use Konekt\Concord\Routing\RouteRegistrar;
21
use ReflectionClass;
22
23
abstract class BaseServiceProvider extends ServiceProvider implements Module
24
{
25
    /** @var  string */
26
    protected $basePath;
27
28
    /** @var  Manifest */
29
    protected $manifest;
30
31
    /** @var  string */
32
    protected $namespaceRoot;
33
34
    /** @var  string */
35
    protected $id;
36
37
    /** @var  array */
38
    protected $models = [];
39
40
    /** @var  array */
41
    protected $enums = [];
42
43
    /** @var  array */
44
    protected $requests = [];
45
46
    /** @var  ConcordContract */
47
    protected $concord;
48
49
    /** @var  Convention */
50
    protected $convention;
51
52
    /** @var  Kind */
53
    protected $kind;
54
55
    /**
56
     * ModuleServiceProvider class constructor
57
     *
58
     * @param \Illuminate\Contracts\Foundation\Application $app
59
     */
60
    public function __construct($app)
61
    {
62
        parent::__construct($app);
63
64
        $this->concord       = $app->make(ConcordContract::class); // retrieve the concord singleton
65
        $this->convention    = $this->concord->getConvention(); // storing to get rid of train wrecks
66
        $this->kind          = Kind::create(static::$_kind);
67
        $this->basePath      = dirname(dirname((new ReflectionClass(static::class))->getFileName()));
68
        $this->namespaceRoot = str_replace(
69
                                    sprintf('\\%s\\ModuleServiceProvider',
70
                                        str_replace('/', '\\', $this->convention->providersFolder())
71
                                    ),
72
                                    '', static::class
73
                                );
74
        $this->id            = $this->getModuleId();
75
    }
76
77
    public function register()
78
    {
79
        $this->loadConfiguration();
80
81
        if (true === $this->config('event_listeners')) {
82
            $this->registerEventServiceProvider();
83
        }
84
    }
85
86
    /**
87
     * @inheritdoc
88
     */
89
    public function boot()
90
    {
91
        if ($this->areMigrationsEnabled()) {
92
            $this->registerMigrations();
93
        }
94
95
        if ($this->areModelsEnabled()) {
96
            $this->registerModels();
97
            $this->registerEnums();
98
            $this->registerRequestTypes();
99
        }
100
101
        if ($this->areViewsEnabled()) {
102
            $this->registerViews();
103
        }
104
105
        if ($routes = $this->config('routes', true)) {
106
            $this->registerRoutes($routes);
107
        }
108
109
        $this->publishes([
110
            $this->getBasePath() . '/' . $this->convention->migrationsFolder() =>
111
                database_path('migrations')
112
        ], 'migrations');
113
    }
114
115
    public function areMigrationsEnabled(): bool
116
    {
117
        return (bool) $this->config('migrations', true);
118
    }
119
120
    public function areModelsEnabled(): bool
121
    {
122
        return (bool) $this->config('models', true);
123
    }
124
125
    public function areViewsEnabled(): bool
126
    {
127
        return (bool) $this->config('views', true);
128
    }
129
130
    public function areRoutesEnabled(): bool
131
    {
132
        return (bool) $this->config('routes', true);
133
    }
134
135
    /**
136
     * @inheritDoc
137
     */
138
    public function getId(): string
139
    {
140
        return $this->id;
141
    }
142
143
    /**
144
     * Returns module configuration value(s)
145
     *
146
     * @param string $key If left empty, the entire module configuration gets retrieved
147
     * @param mixed  $default
148
     *
149
     * @return mixed
150
     */
151
    public function config(string $key = null, $default = null)
152
    {
153
        $key = $key ? sprintf('%s.%s', $this->getId(), $key) : $this->getId();
154
155
        return config($key, $default);
156
    }
157
158
    /**
159
     * @return Manifest
160
     */
161
    public function getManifest(): Manifest
162
    {
163
        if (!$this->manifest) {
164
            $data = include($this->basePath . '/' . $this->convention->manifestFile());
165
166
            $name    = $data['name'] ?? 'N/A';
167
            $version = $data['version'] ?? 'n/a';
168
169
            $this->manifest = new Manifest($name, $version);
170
        }
171
172
        return $this->manifest;
173
    }
174
175
    /**
176
     * Returns the root folder on the filesystem containing the module
177
     *
178
     * @return string
179
     */
180
    public function getBasePath(): string
181
    {
182
        return $this->basePath;
183
    }
184
185
    /**
186
     * @inheritdoc
187
     */
188
    public function getKind(): Kind
189
    {
190
        return $this->kind;
191
    }
192
193
    /**
194
     * Returns the folder where the module/box configuration files are
195
     *
196
     * @return string
197
     */
198
    public function getConfigPath(): string
199
    {
200
        return $this->getBasePath() . '/' . $this->convention->configFolder();
201
    }
202
203
    /**
204
     * Returns the module's root (topmost) namespace
205
     *
206
     * @return string
207
     */
208
    public function getNamespaceRoot(): string
209
    {
210
        return $this->namespaceRoot;
211
    }
212
213
    /**
214
     * Returns the short (abbreviated) name of the module
215
     * E.g. Konekt\AppShell => app_shell
216
     */
217
    public function shortName()
218
    {
219
        $id = $this->getModuleId();
220
        $p  = strrpos($id, '.');
221
222
        return $p ? substr($id, $p + 1) : $id;
223
    }
224
225
    /**
226
     * Returns a standard module name based on the module provider's classname
227
     *
228
     * Eg.: '\Vendor\Module\Services\ModuleServiceProvider' -> 'vendor.module'
229
     *
230
     * @param string    $classname
231
     *
232
     * @see concord_module_id
233
     *
234
     * @return string
235
     */
236
    protected function getModuleId($classname = null)
237
    {
238
        return concord_module_id($classname ?: static::class);
239
    }
240
241
    /**
242
     * Register the module's migrations
243
     */
244
    protected function registerMigrations()
245
    {
246
        $path = $this->getBasePath() . '/' . $this->convention->migrationsFolder();
247
248
        if ($this->app->runningInConsole() && is_dir($path)) {
249
            $this->loadMigrationsFrom($path);
250
        }
251
    }
252
253
    /**
254
     * Register models in a box/module
255
     */
256
    protected function registerModels()
257
    {
258
        foreach ($this->models as $key => $model) {
259
            $contract = is_string($key) ? $key : $this->convention->contractForModel($model);
260
            $this->concord->registerModel($contract, $model);
261
        }
262
    }
263
264
    /**
265
     * Register enums in a box/module
266
     */
267
    protected function registerEnums()
268
    {
269
        foreach ($this->enums as $key => $enum) {
270
            $contract = is_string($key) ? $key : $this->convention->contractForEnum($enum);
271
            $this->concord->registerEnum($contract, $enum);
272
        }
273
    }
274
275
    /**
276
     * Register request types in a box/module
277
     */
278
    protected function registerRequestTypes()
279
    {
280
        foreach ($this->requests as $key => $requestType) {
281
            $contract = is_string($key) ? $key : $this->convention->contractForRequest($requestType);
282
            $this->concord->registerRequest($contract, $requestType);
283
        }
284
    }
285
286
    /**
287
     * Register the views folder, in a separate namespace
288
     */
289
    protected function registerViews()
290
    {
291
        $path      = $this->getBasePath() . '/' . $this->convention->viewsFolder();
292
        $namespace = $this->config('views.namespace', $this->shortName());
293
294
        if (is_dir($path)) {
295
            $this->loadViewsFrom($path, $namespace);
296
        }
297
    }
298
299
    /**
300
     * Registers the event service provider of the module/config (ie. event-listener bindings)
301
     */
302
    protected function registerEventServiceProvider()
303
    {
304
        $eventServiceProviderClass = sprintf('%s\\%s\\EventServiceProvider',
305
            $this->namespaceRoot,
306
            str_replace('/', '\\', $this->convention->providersFolder())
307
        );
308
309
        if (class_exists($eventServiceProviderClass)) {
310
            $this->app->register($eventServiceProviderClass);
311
        }
312
    }
313
314
    protected function loadConfiguration()
315
    {
316
        $cfgFile = sprintf('%s/%s', $this->getConfigPath(), $this->configFileName);
317
318
        if (file_exists($cfgFile)) {
319
            $this->mergeConfigFrom($cfgFile, $this->getId());
320
        }
321
    }
322
323
    protected function registerRoutes($routes): void
324
    {
325
        $routeRegistrar = new RouteRegistrar($this, $this->convention);
326
        if (true === $routes) {
327
            $routeRegistrar->registerAllRoutes();
328
        } elseif (isset($routes['files'])) {
329
            $routeRegistrar->registerRoutes($this->config('routes.files'), $this->config('routes'));
330
        } elseif (isset($routes[0]) && is_array($routes[0])) {
331
            foreach ($routes as $route) {
332
                $routeRegistrar->registerRoutes($route['files'], $route);
333
            }
334
        }
335
    }
336
}
337