Completed
Push — master ( d6c0d3...fbf2bc )
by Sergi Tur
03:14
created

AdminLTERoute   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 383
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 45
c 0
b 0
f 0
lcom 1
cbo 10
dl 0
loc 383
rs 8.3673

27 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A handle() 0 10 1
A mountpoint() 0 5 2
A destinationFile() 0 4 2
A warnIfRouteAlreadyExists() 0 9 3
A routeExists() 0 5 2
A webRouteExists() 0 11 4
A removeTrailingSlashIfExists() 0 4 2
A removeDuplicatedTrailingSlashes() 0 4 1
A apiRouteExists() 0 4 1
A createTmpFileWithRoute() 0 6 1
A getPath() 0 4 1
A getRouteCode() 0 15 2
A method() 0 5 2
A action() 0 7 2
A processInput() 0 5 1
A validateMethod() 0 6 2
A validateType() 0 6 2
A postActions() 0 5 2
A createAction() 0 6 4
A createView() 0 7 1
A createController() 0 8 1
A createResourceController() 0 8 1
A addMethodToController() 0 6 1
A createTmpFileWithMethod() 0 6 1
A getMethodCode() 0 9 1
A getMethodStubPath() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like AdminLTERoute often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AdminLTERoute, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Acacha\AdminLTETemplateLaravel\Console;
4
5
use Acacha\AdminLTETemplateLaravel\Compiler\StubFileCompiler;
6
use Acacha\AdminLTETemplateLaravel\Console\Routes\Controller;
7
use Acacha\AdminLTETemplateLaravel\Console\Routes\ControllerResourceRoute;
8
use Acacha\AdminLTETemplateLaravel\Console\Routes\ControllerRoute;
9
use Acacha\AdminLTETemplateLaravel\Console\Routes\GeneratesCode;
10
use Acacha\AdminLTETemplateLaravel\Console\Routes\RegularRoute;
11
use Acacha\AdminLTETemplateLaravel\Exceptions\RouteTypeNotValid;
12
use Acacha\AdminLTETemplateLaravel\Filesystem\Filesystem;
13
use Illuminate\Console\Command;
14
use Illuminate\Routing\Router;
15
use Illuminate\Support\Facades\Artisan;
16
use Route;
17
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
18
19
/**
20
 * Class AdminLTERoute.
21
 */
22
class AdminLTERoute extends Command
23
{
24
    use HasUsername, HasEmail, Controller;
25
26
    /**
27
     * Path to web routes file.
28
     *
29
     * @var string
30
     */
31
    protected $web_routes_path = 'routes/web.php';
32
33
    /**
34
     * Path to api routes file.
35
     *
36
     * @var string
37
     */
38
    protected $api_routes_path = 'routes/api.php';
39
40
    /**
41
     * Compiler for stub file.
42
     *
43
     * @var StubFileCompiler
44
     */
45
    protected $compiler;
46
47
    /**
48
     * Compiler for stub file.
49
     *
50
     * @var Filesystem
51
     */
52
    protected $filesystem;
53
54
    /**
55
     * @var array
56
     */
57
    protected static $lookup = [
58
        'regular' => RegularRoute::class,
59
        'controller' => ControllerRoute::class,
60
        'resource' => ControllerResourceRoute::class,
61
    ];
62
63
    /**
64
     * The name and signature of the console command.
65
     */
66
    protected $signature = 'adminlte-laravel:route {link: The route link} {action? : View or controller to create} {--t|type=regular : Type of route to create (regular,controller,resource)} {--m|method=get : HTTP method} {--api : Route is an api route} {--a|createaction : Create view or controller after route}';
67
68
    /**
69
     * The console command description.
70
     *
71
     * @var string
72
     */
73
    protected $description = 'Insert a route to routes/web.php file';
74
75
    /**
76
     * AdminLTERoute constructor.
77
     *
78
     * @param StubFileCompiler $compiler
79
     * @param Filesystem $filesystem
80
     */
81
    public function __construct(StubFileCompiler $compiler, Filesystem $filesystem)
82
    {
83
        parent::__construct();
84
        $this->compiler = $compiler;
85
        $this->filesystem = $filesystem;
86
    }
87
88
    /**
89
     * Execute the console command.
90
     */
91
    public function handle()
92
    {
93
        $this->processInput();
94
        $this->warnIfRouteAlreadyExists($link = $this->argument('link'));
95
        $tmpfile = $this->createTmpFileWithRoute();
96
        $path = $this->getPath($tmpfile);
97
        add_file_into_file($this->mountpoint(), $path, $dstFile = $this->destinationFile() );
98
        $this->info('Route ' . $link . ' added to ' .  $dstFile . '.');
99
        $this->postActions();
100
    }
101
102
    /**
103
     * Get mountpoint.
104
     *
105
     * @return string
106
     */
107
    protected function mountpoint()
108
    {
109
        if ($this->option('api')) return '#adminlte_api_routes';
110
        return '#adminlte_routes';
111
    }
112
113
    /**
114
     * Destination route file.
115
     *
116
     * @return string
117
     */
118
    protected function destinationFile() {
119
        if ($this->option('api')) return base_path($this->api_routes_path);
120
        return base_path($this->web_routes_path);
121
    }
122
123
    /**
124
     * Warn if route already exists.
125
     *
126
     * @param $link
127
     */
128
    protected function warnIfRouteAlreadyExists($link)
129
    {
130
        if ($this->routeExists($link)) {
131
            if ($this->confirm('Route already exists. Do you wish to continue?')) {
132
                return;
133
            }
134
            die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method warnIfRouteAlreadyExists() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
135
        }
136
    }
137
138
    /**
139
     * Check if route exists.
140
     *
141
     * @param $link
142
     * @return mixed
143
     */
144
    protected function routeExists($link)
145
    {
146
        if ($this->option('api')) return $this->apiRouteExists($link);
147
        return $this->webRouteExists($link);
148
    }
149
150
    /**
151
     * Check if web route exists.
152
     *
153
     * @param $link
154
     * @return mixed
155
     */
156
    protected function webRouteExists($link)
157
    {
158
        $link = $this->removeTrailingSlashIfExists($link);
159
        $link = $this->removeDuplicatedTrailingSlashes($link);
160
        foreach (Route::getRoutes() as $value) {
161
            if (in_array(strtoupper($this->option('method')), array_merge($value->getMethods(), ['ANY'])) && $value->getPath() === $link) {
162
                return true;
163
            }
164
        }
165
        return false;
166
    }
167
168
    /**
169
     * Remove (if exists) trailing slash from link.
170
     *
171
     * @param $link
172
     * @return string
173
     */
174
    protected function removeTrailingSlashIfExists($link){
175
        if (starts_with($link,'/')) return substr($link, 1);
176
        return $link;
177
    }
178
179
    /**
180
     * Remove duplicated trailing slashes.
181
     *
182
     * @param $link
183
     * @return mixed
184
     */
185
    protected function removeDuplicatedTrailingSlashes($link)
186
    {
187
        return preg_replace('/(\/+)/','/',$link);
188
    }
189
190
    /**
191
     * Check if api route exists.
192
     *
193
     * @param $link
194
     * @return mixed
195
     */
196
    protected function apiRouteExists($link)
197
    {
198
        return $this->webRouteExists('api/v1/' . $link);
199
    }
200
201
    /**
202
     * Crete tmp file with route to add.
203
     *
204
     * @return mixed
205
     */
206
    protected function createTmpFileWithRoute()
207
    {
208
        $temp = tmpfile();
209
        fwrite($temp, $this->getRouteCode());
210
        return $temp;
211
    }
212
213
    /**
214
     * Get path from file resource.
215
     *
216
     * @param $tmpfile
217
     * @return mixed
218
     */
219
    protected function getPath($tmpfile)
220
    {
221
        return stream_get_meta_data($tmpfile)['uri'];
222
    }
223
224
    /**
225
     * Get route code to insert depending on type.
226
     *
227
     * @return mixed
228
     */
229
    protected function getRouteCode()
230
    {
231
        $type = $this->option('type');
232
        $class = isset(static::$lookup[$type])
233
            ? static::$lookup[$type]
234
            : RegularRoute::class;
235
        /** @var GeneratesCode $route */
236
        $route = new $class($this->compiler,$this->filesystem);
237
        $route->setReplacements([
238
            $this->argument('link'),
239
            $this->action(),
240
            $this->method()
241
        ]);
242
        return $route->code();
243
    }
244
245
    /**
246
     * Get method.
247
     *
248
     * @return string
249
     */
250
    protected function method()
251
    {
252
        if ( strtolower($this->option('method')) == 'head' ) return 'get';
253
        return strtolower($this->option('method'));
254
    }
255
256
    /**
257
     * Get the action replacement.
258
     *
259
     * @return array|string
260
     */
261
    protected function action()
262
    {
263
        if ($this->argument('action') != null) {
264
            return $this->argument('action');
265
        }
266
        return $this->argument('link');
267
    }
268
269
    /**
270
     * Process input.
271
     */
272
    protected function processInput()
273
    {
274
        $this->validateMethod();
275
        $this->validateType();
276
    }
277
278
    /**
279
     * Validate option method.
280
     */
281
    protected function validateMethod()
282
    {
283
        if (! in_array(strtoupper($this->option('method')), $methods = array_merge(Router::$verbs, ['ANY']))) {
284
            throw new MethodNotAllowedException($methods);
285
        }
286
    }
287
288
    /**
289
     * Validate option type.
290
     */
291
    protected function validateType()
292
    {
293
        if (! in_array( strtolower($this->option('type')),['regular','controller','resource'])) {
294
            throw new RouteTypeNotValid();
295
        }
296
    }
297
298
    /**
299
     * Execute post actions (if exists)
300
     */
301
    protected function postActions()
302
    {
303
        if ($this->option('createaction') != null) $this->createAction();
304
305
    }
306
307
    /**
308
     * Create action (view|controller).
309
     */
310
    protected function createAction()
311
    {
312
        if (strtolower($this->option('type')) == 'regular' || $this->option('type') == null) return $this->createView();
313
        if (strtolower($this->option('type')) == 'controller') return $this->createController();
314
        return $this->createResourceController();
315
    }
316
317
    /**
318
     * Create View.
319
     */
320
    protected function createView()
321
    {
322
        Artisan::call('make:view', [
323
            'name' => $this->action()
324
        ]);
325
        $this->info('View ' . $this->action() .'.blade.php created.');
326
    }
327
328
    /**
329
     * Create regular controller.
330
     */
331
    protected function createController()
332
    {
333
        Artisan::call('make:controller', [
334
            'name' => $controller = $this->controllerWithoutMethod($this->action())
335
        ]);
336
        $this->addMethodToController($controller,$this->controllerMethod($this->action()));
337
        $this->info('Controller ' . $controller .' created.');
338
    }
339
340
    /**
341
     * Create resource controller.
342
     */
343
    protected function createResourceController()
344
    {
345
        Artisan::call('make:controller', [
346
            'name' => $controller = $this->controllerWithoutMethod($this->action()),
347
            '--resource' => true
348
        ]);
349
        $this->info('Resource Controller ' . $controller .' created.');
350
    }
351
352
    /**
353
     * Add method to controller.
354
     *
355
     * @param $controller
356
     * @param $controllerMethod     *
357
     */
358
    protected function addMethodToController($controller, $controllerMethod)
359
    {
360
        $tmpfile = $this->createTmpFileWithMethod($controllerMethod);
361
        $path = $this->getPath($tmpfile);
362
        add_file_into_file('\/\/',$path,app_path('Http/Controllers/' . $controller . '.php'));
363
    }
364
365
    /**
366
     * Crete tmp file with route to add.
367
     *
368
     * @param $controllerMethod
369
     * @return mixed
370
     */
371
    protected function createTmpFileWithMethod($controllerMethod)
372
    {
373
        $temp = tmpfile();
374
        fwrite($temp, $this->getMethodCode($controllerMethod));
375
        return $temp;
376
    }
377
378
    /**
379
     * Get method code.
380
     *
381
     * @param $controllerMethod
382
     * @return mixed
383
     */
384
    protected function getMethodCode($controllerMethod)
385
    {
386
        return $this->compiler->compile(
387
            $this->filesystem->get($this->getMethodStubPath()),
388
            [
389
                'METHOD' => $controllerMethod
390
            ]
391
        );
392
    }
393
394
    /**
395
     * Get method stub path.
396
     *
397
     * @return string
398
     */
399
    protected function getMethodStubPath()
400
    {
401
        return __DIR__ . '/stubs/method.stub';
402
    }
403
404
}
405