Completed
Push — master ( 46f2ed...29c113 )
by Attila
07:51 queued 31s
created

BaseServiceProvider::getKind()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
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
13
namespace Konekt\Concord;
14
15
use Illuminate\Support\Facades\File;
16
use Illuminate\Support\ServiceProvider;
17
use Illuminate\Support\Facades\Route;
18
use Konekt\Concord\Contracts\Concord as ConcordContract;
19
use Konekt\Concord\Contracts\Convention;
20
use Konekt\Concord\Contracts\Module;
21
use Konekt\Concord\Module\Manifest;
22
use Konekt\Concord\Module\Kind;
23
use ReflectionClass;
24
25
abstract class BaseServiceProvider extends ServiceProvider implements Module
26
{
27
    /** @var  string */
28
    protected $basePath;
29
30
    /** @var  Manifest */
31
    protected $manifest;
32
33
    /** @var  string */
34
    protected $namespaceRoot;
35
36
    /** @var  string */
37
    protected $id;
38
39
    /** @var  array */
40
    protected $models = [];
41
42
    /** @var  array */
43
    protected $enums = [];
44
45
    /** @var  array */
46
    protected $requests = [];
47
48
    /** @var  ConcordContract */
49
    protected $concord;
50
51
    /** @var  Convention */
52
    protected $convention;
53
54
    /** @var  Kind */
55
    protected $kind;
56
57
    /**
58
     * ModuleServiceProvider class constructor
59
     *
60
     * @param \Illuminate\Contracts\Foundation\Application $app
61
     */
62
    public function __construct($app)
63
    {
64
        parent::__construct($app);
65
66
        $this->concord       = $app->make(ConcordContract::class); // retrieve the concord singleton
67
        $this->convention    = $this->concord->getConvention(); // storing to get rid of train wrecks
68
        $this->kind          = Kind::create(static::$_kind);
69
        $this->basePath      = dirname(dirname((new ReflectionClass(static::class))->getFileName()));
70
        $this->namespaceRoot = str_replace(
71
                                    sprintf('\\%s\\ModuleServiceProvider',
72
                                        str_replace('/', '\\', $this->convention->providersFolder())
73
                                    ),
74
                                    '', static::class
75
                                );
76
        $this->id            = $this->getModuleId();
77
    }
78
79
    public function register()
80
    {
81
        $this->loadConfiguration();
82
83
        if ($this->config('event_listeners') === true) {
84
            $this->registerEventServiceProvider();
85
        }
86
    }
87
88
    /**
89
     * @inheritdoc
90
     */
91
    public function boot()
92
    {
93
        if ($this->config('migrations', true)) {
94
            $this->registerMigrations();
95
        }
96
97
        if ($this->config('models', true)) {
98
            $this->registerModels();
99
            $this->registerEnums();
100
            $this->registerRequestTypes();
101
        }
102
103
        if ($this->config('views', true)) {
104
            $this->registerViews();
105
        }
106
107
        if ($this->config('routes', true)) {
108
            $this->registerRoutes($this->config('routes.files'));
109
        }
110
    }
111
112
    /**
113
     * @inheritDoc
114
     */
115
    public function getId(): string
116
    {
117
        return $this->id;
118
    }
119
120
    /**
121
     * Returns module configuration value(s)
122
     *
123
     * @param string $key If left empty, the entire module configuration gets retrieved
124
     * @param null   $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
125
     *
126
     * @return mixed
127
     */
128
    public function config(string $key = null, $default = null)
129
    {
130
        $key = $key ? sprintf('%s.%s', $this->getId(), $key) : $this->getId();
131
132
        return config($key, $default);
133
    }
134
135
136
    /**
137
     * @return Manifest
138
     */
139
    public function getManifest(): Manifest
140
    {
141
        if (!$this->manifest) {
142
            $data = include($this->basePath . '/' . $this->convention->manifestFile());
143
144
            $name    = $data['name'] ?? 'N/A';
145
            $version = $data['version'] ?? 'n/a';
146
147
            $this->manifest = new Manifest($name, $version);
148
        }
149
150
        return $this->manifest;
151
    }
152
153
    /**
154
     * Returns the root folder on the filesystem containing the module
155
     *
156
     * @return string
157
     */
158
    public function getBasePath(): string
159
    {
160
        return $this->basePath;
161
    }
162
163
    /**
164
     * @inheritdoc
165
     */
166
    public function getKind(): Kind
167
    {
168
        return $this->kind;
169
    }
170
171
    /**
172
     * Returns the folder where the module/box configuration files are
173
     *
174
     * @return string
175
     */
176
    public function getConfigPath(): string
177
    {
178
        return $this->getBasePath() . '/' . $this->convention->configFolder();
179
    }
180
181
    /**
182
     * Returns the module's root (topmost) namespace
183
     *
184
     * @return string
185
     */
186
    public function getNamespaceRoot(): string
187
    {
188
        return $this->namespaceRoot;
189
    }
190
191
    /**
192
     * Returns the short (abbreviated) name of the module
193
     * E.g. Konekt\AppShell => app_shell
194
     */
195
    public function shortName()
196
    {
197
        $id = $this->getModuleId();
198
        $p  = strrpos($id, '.');
199
200
        return $p ? substr($id, $p + 1) : $id;
201
    }
202
203
204
    /**
205
     * Returns a standard module name based on the module provider's classname
206
     *
207
     * Eg.: '\Vendor\Module\Services\ModuleServiceProvider' -> 'vendor.module'
208
     *
209
     * @param string    $classname
210
     *
211
     * @see concord_module_id
212
     *
213
     * @return string
214
     */
215
    protected function getModuleId($classname = null)
216
    {
217
        return concord_module_id($classname ?: static::class);
218
    }
219
220
    /**
221
     * Register the module's migrations
222
     */
223
    protected function registerMigrations()
224
    {
225
        $path = $this->getBasePath() . '/' . $this->convention->migrationsFolder();
226
227
        if ($this->app->runningInConsole() && is_dir($path)) {
228
            $this->loadMigrationsFrom($path);
229
        }
230
    }
231
232
    /**
233
     * Register models in a box/module
234
     */
235
    protected function registerModels()
236
    {
237
        foreach ($this->models as $key => $model) {
238
            $contract = is_string($key) ? $key : $this->convention->contractForModel($model);
239
            $this->concord->registerModel($contract, $model);
240
        }
241
    }
242
243
    /**
244
     * Register enums in a box/module
245
     */
246
    protected function registerEnums()
247
    {
248
        foreach ($this->enums as $key => $enum) {
249
            $contract = is_string($key) ? $key : $this->convention->contractForEnum($enum);
250
            $this->concord->registerEnum($contract, $enum);
251
        }
252
    }
253
254
    /**
255
     * Register request types in a box/module
256
     */
257
    protected function registerRequestTypes()
258
    {
259
        foreach ($this->requests as $key => $requestType) {
260
            $contract = is_string($key) ? $key : $this->convention->contractForRequest($requestType);
261
            $this->concord->registerRequest($contract, $requestType);
262
        }
263
    }
264
265
    /**
266
     * Register routes in a box/module
267
     *
268
     * @param array|string $files Pass '*' to register all the route files in routes/ folder
269
     *                            or an array with the list of route files to register
270
     */
271
    protected function registerRoutes($files = null)
272
    {
273
        $path = $this->getBasePath() . '/' . $this->convention->routesFolder();
274
275
        if (is_dir($path)) {
276
            $routes = is_array($files) ? $files : collect(File::glob($path . '/*.php'))->map(function ($file) {
277
                return File::name($file);
278
            })->all();
279
280
            foreach ($routes as $route) {
281
                Route::group(
282
                    [
283
                        'namespace'  => $this->config('routes.namespace', $this->getDefaultRouteNamespace()),
284
                        'prefix'     => $this->config('routes.prefix', $this->shortName()),
285
                        'as'         => $this->config('routes.as', $this->shortName() . '.'),
286
                        'middleware' => $this->config('routes.middleware', ['web'])
287
                    ],
288
                    sprintf('%s/%s.php', $path, $route)
0 ignored issues
show
Unused Code introduced by
The call to Illuminate\Support\Facades\Route::group() has too many arguments starting with sprintf('%s/%s.php', $path, $route). ( Ignorable by Annotation )

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

288
                Route::/** @scrutinizer ignore-call */ 
289
                       group(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
289
                );
290
            }
291
        }
292
    }
293
294
    /**
295
     * Register the views folder, in a separate namespace
296
     */
297
    protected function registerViews()
298
    {
299
        $path      = $this->getBasePath() . '/' . $this->convention->viewsFolder();
300
        $namespace = $this->config('views.namespace', $this->shortName());
301
302
        if (is_dir($path)) {
303
            $this->loadViewsFrom($path, $namespace);
304
        }
305
    }
306
307
    /**
308
     * Registers the event service provider of the module/config (ie. event-listener bindings)
309
     */
310
    protected function registerEventServiceProvider()
311
    {
312
        $eventServiceProviderClass = sprintf('%s\\%s\\EventServiceProvider',
313
            $this->namespaceRoot,
314
            str_replace('/', '\\', $this->convention->providersFolder())
315
        );
316
317
        if (class_exists($eventServiceProviderClass)) {
318
            $this->app->register($eventServiceProviderClass);
319
        }
320
    }
321
322
    protected function loadConfiguration()
323
    {
324
        $cfgFile = sprintf('%s/%s', $this->getConfigPath(), $this->configFileName);
325
326
        if (file_exists($cfgFile)) {
327
            $this->mergeConfigFrom($cfgFile, $this->getId());
328
        }
329
    }
330
331
    /**
332
     * Returns the default namespace for routes/controllers within a box/module
333
     *
334
     * @return string
335
     */
336
    protected function getDefaultRouteNamespace()
337
    {
338
        return sprintf('%s\\%s',
339
            $this->getNamespaceRoot(),
340
            str_replace('/', '\\', $this->convention->controllersFolder())
341
        );
342
    }
343
}
344