Completed
Push — master ( 05782f...515813 )
by Sergi Tur
03:26
created

MakeRoute::action()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 3
eloc 5
nc 3
nop 0
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 MakeRoute.
21
 */
22
class MakeRoute 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 = 'make:route {link : The route link} {action? : View or controller to create} 
67
    {--t|type=regular : Type of route to create (regular,controller,resource)} {--m|method=get : HTTP method} 
68
    {--api : Route is an api route} {--a|createaction : Create view or controller after route}';
69
70
    /**
71
     * The console command description.
72
     *
73
     * @var string
74
     */
75
    protected $description = 'Insert a route to routes/web.php file';
76
77
    /**
78
     * AdminLTERoute constructor.
79
     *
80
     * @param StubFileCompiler $compiler
81
     * @param Filesystem $filesystem
82
     */
83
    public function __construct(StubFileCompiler $compiler, Filesystem $filesystem)
84
    {
85
        parent::__construct();
86
        $this->compiler = $compiler;
87
        $this->filesystem = $filesystem;
88
    }
89
90
    /**
91
     * Execute the console command.
92
     */
93
    public function handle()
94
    {
95
        $this->processInput();
96
        $this->warnIfRouteAlreadyExists($link = $this->argument('link'));
97
        $tmpfile = $this->createTmpFileWithRoute();
98
        $path = $this->getPath($tmpfile);
99
        add_file_into_file($this->mountpoint(), $path, $dstFile = $this->destinationFile());
100
        $this->info('Route ' . $link . ' added to ' .  $dstFile . '.');
101
        $this->postActions();
102
    }
103
104
    /**
105
     * Get mountpoint.
106
     *
107
     * @return string
108
     */
109
    protected function mountpoint()
110
    {
111
        if ($this->option('api')) {
112
            return '#adminlte_api_routes';
113
        }
114
        return '#adminlte_routes';
115
    }
116
117
    /**
118
     * Destination route file.
119
     *
120
     * @return string
121
     */
122
    protected function destinationFile()
123
    {
124
        if ($this->option('api')) {
125
            return base_path($this->api_routes_path);
126
        }
127
        return base_path($this->web_routes_path);
128
    }
129
130
    /**
131
     * Warn if route already exists.
132
     *
133
     * @param $link
134
     */
135
    protected function warnIfRouteAlreadyExists($link)
136
    {
137
        if ($this->routeExists($link)) {
138
            if ($this->confirm('Route already exists. Do you wish to continue?')) {
139
                return;
140
            }
141
            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...
142
        }
143
    }
144
145
    /**
146
     * Check if route exists.
147
     *
148
     * @param $link
149
     * @return mixed
150
     */
151
    protected function routeExists($link)
152
    {
153
        if ($this->option('api')) {
154
            return $this->apiRouteExists($link);
155
        }
156
        return $this->webRouteExists($link);
157
    }
158
159
    /**
160
     * Check if web route exists.
161
     *
162
     * @param $link
163
     * @return mixed
164
     */
165
    protected function webRouteExists($link)
166
    {
167
        $link = $this->removeTrailingSlashIfExists($link);
168
        $link = $this->removeDuplicatedTrailingSlashes($link);
169
        foreach (Route::getRoutes() as $value) {
170
            if (in_array(strtoupper($this->option('method')), array_merge($value->getMethods(), ['ANY'])) &&
171
                $value->getPath() === $link) {
172
                return true;
173
            }
174
        }
175
        return false;
176
    }
177
178
    /**
179
     * Remove (if exists) trailing slash from link.
180
     *
181
     * @param $link
182
     * @return string
183
     */
184
    protected function removeTrailingSlashIfExists($link)
185
    {
186
        if (starts_with($link, '/')) {
187
            return substr($link, 1);
188
        }
189
        return $link;
190
    }
191
192
    /**
193
     * Remove duplicated trailing slashes.
194
     *
195
     * @param $link
196
     * @return mixed
197
     */
198
    protected function removeDuplicatedTrailingSlashes($link)
199
    {
200
        return preg_replace('/(\/+)/', '/', $link);
201
    }
202
203
    /**
204
     * Check if api route exists.
205
     *
206
     * @param $link
207
     * @return mixed
208
     */
209
    protected function apiRouteExists($link)
210
    {
211
        return $this->webRouteExists('api/v1/' . $link);
212
    }
213
214
    /**
215
     * Crete tmp file with route to add.
216
     *
217
     * @return mixed
218
     */
219
    protected function createTmpFileWithRoute()
220
    {
221
        $temp = tmpfile();
222
        fwrite($temp, $this->getRouteCode());
223
        return $temp;
224
    }
225
226
    /**
227
     * Get path from file resource.
228
     *
229
     * @param $tmpfile
230
     * @return mixed
231
     */
232
    protected function getPath($tmpfile)
233
    {
234
        return stream_get_meta_data($tmpfile)['uri'];
235
    }
236
237
    /**
238
     * Get route code to insert depending on type.
239
     *
240
     * @return mixed
241
     */
242
    protected function getRouteCode()
243
    {
244
        $type = $this->option('type');
245
        $class = isset(static::$lookup[$type])
246
            ? static::$lookup[$type]
247
            : RegularRoute::class;
248
        /** @var GeneratesCode $route */
249
        $route = new $class($this->compiler, $this->filesystem);
250
        $route->setReplacements([
251
            $this->argument('link'),
252
            $this->action(),
253
            $this->method()
254
        ]);
255
        return $route->code();
256
    }
257
258
    /**
259
     * Get method.
260
     *
261
     * @return string
262
     */
263
    protected function method()
264
    {
265
        if (strtolower($this->option('method')) == 'head') {
266
            return 'get';
267
        }
268
        return strtolower($this->option('method'));
269
    }
270
271
    /**
272
     * Get the action replacement.
273
     *
274
     * @return array|string
275
     */
276
    protected function action()
277
    {
278
        if ($this->argument('action') != null) {
279
            return $this->argument('action');
280
        }
281
        if (strtolower($this->option('type')) != 'regular' ) return $this->argument('link') . 'Controller';
282
        return $this->argument('link');
283
    }
284
285
    /**
286
     * Process input.
287
     */
288
    protected function processInput()
289
    {
290
        $this->validateMethod();
291
        $this->validateType();
292
    }
293
294
    /**
295
     * Validate option method.
296
     */
297
    protected function validateMethod()
298
    {
299
        if (! in_array(strtoupper($this->option('method')), $methods = array_merge(Router::$verbs, ['ANY']))) {
300
            throw new MethodNotAllowedException($methods);
301
        }
302
    }
303
304
    /**
305
     * Validate option type.
306
     */
307
    protected function validateType()
308
    {
309
        if (! in_array(strtolower($this->option('type')), ['regular','controller','resource'])) {
310
            throw new RouteTypeNotValid();
311
        }
312
    }
313
314
    /**
315
     * Execute post actions (if exists)
316
     */
317
    protected function postActions()
318
    {
319
        if ($this->option('createaction') != null) {
320
            $this->createAction();
321
        }
322
    }
323
324
    /**
325
     * Create action (view|controller).
326
     */
327
    protected function createAction()
328
    {
329
        if (strtolower($this->option('type')) == 'regular' || $this->option('type') == null) {
330
            return $this->createView();
331
        }
332
        if (strtolower($this->option('type')) == 'controller') {
333
            return $this->createController();
334
        }
335
        return $this->createResourceController();
336
    }
337
338
    /**
339
     * Create View.
340
     *
341
     * @param null $name
342
     */
343
    protected function createView($name = null)
344
    {
345
        if ($name == null) $name = $this->action();
346
        Artisan::call('make:view', [
347
            'name' => $name
348
        ]);
349
        $this->info('View ' . $name .'.blade.php created.');
350
    }
351
352
    /**
353
     * Create regular controller.
354
     */
355
    protected function createController()
356
    {
357
        Artisan::call('make:controller', [
358
            'name' => $controller = $this->controllerWithoutMethod($this->action())
359
        ]);
360
        $this->addMethodToController($controller, $this->controllerMethod($this->action()));
361
        $this->info('Controller ' . $controller .' created.');
362
        $this->createView($this->argument('link'));
363
    }
364
365
    /**
366
     * Create resource controller.
367
     */
368
    protected function createResourceController()
369
    {
370
        Artisan::call('make:controller', [
371
            'name' => $controller = $this->controllerWithoutMethod($this->action()),
372
            '--resource' => true
373
        ]);
374
        $this->info('Resource Controller ' . $controller .' created.');
375
        $this->createView($this->argument('link'));
376
    }
377
378
    /**
379
     * Add method to controller.
380
     *
381
     * @param $controller
382
     * @param $controllerMethod     *
383
     */
384
    protected function addMethodToController($controller, $controllerMethod)
385
    {
386
        $tmpfile = $this->createTmpFileWithMethod($controllerMethod);
387
        $path = $this->getPath($tmpfile);
388
        add_file_into_file('\/\/', $path, app_path('Http/Controllers/' . $controller . '.php'));
389
    }
390
391
    /**
392
     * Crete tmp file with route to add.
393
     *
394
     * @param $controllerMethod
395
     * @return mixed
396
     */
397
    protected function createTmpFileWithMethod($controllerMethod)
398
    {
399
        $temp = tmpfile();
400
        fwrite($temp, $this->getMethodCode($controllerMethod));
401
        return $temp;
402
    }
403
404
    /**
405
     * Get method code.
406
     *
407
     * @param $controllerMethod
408
     * @return mixed
409
     */
410
    protected function getMethodCode($controllerMethod)
411
    {
412
        return $this->compiler->compile(
413
            $this->filesystem->get($this->getMethodStubPath()),
414
            [
415
                'METHOD' => $controllerMethod,
416
                'VIEW' => $this->argument('link')
417
            ]
418
        );
419
    }
420
421
    /**
422
     * Get method stub path.
423
     *
424
     * @return string
425
     */
426
    protected function getMethodStubPath()
427
    {
428
        return __DIR__ . '/stubs/method.stub';
429
    }
430
}
431