These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Acacha\AdminLTETemplateLaravel\Console; |
||
4 | |||
5 | use Acacha\AdminLTETemplateLaravel\Console\Routes\Controller; |
||
6 | use Acacha\AdminLTETemplateLaravel\Console\Routes\ControllerResourceRoute; |
||
7 | use Acacha\AdminLTETemplateLaravel\Console\Routes\ControllerRoute; |
||
8 | use Acacha\AdminLTETemplateLaravel\Console\Routes\GeneratesCode; |
||
9 | use Acacha\AdminLTETemplateLaravel\Console\Routes\RegularRoute; |
||
10 | use Acacha\AdminLTETemplateLaravel\Exceptions\RouteTypeNotValid; |
||
11 | use Acacha\AdminLTETemplateLaravel\Exceptions\SpatieMenuDoesNotExists; |
||
12 | use Acacha\Filesystem\Compiler\StubFileCompiler; |
||
13 | use Acacha\Filesystem\Filesystem; |
||
14 | use Illuminate\Console\Command; |
||
15 | use Illuminate\Routing\Router; |
||
16 | use Illuminate\Support\Facades\Artisan; |
||
17 | use Route; |
||
18 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; |
||
19 | |||
20 | /** |
||
21 | * Class MakeRoute. |
||
22 | */ |
||
23 | class MakeRoute extends Command |
||
24 | { |
||
25 | use Controller, CreatesModels; |
||
26 | |||
27 | /** |
||
28 | * Path to web routes file. |
||
29 | * |
||
30 | * @var string |
||
31 | */ |
||
32 | protected $web_routes_path = 'routes/web.php'; |
||
33 | |||
34 | /** |
||
35 | * Path to api routes file. |
||
36 | * |
||
37 | * @var string |
||
38 | */ |
||
39 | protected $api_routes_path = 'routes/api.php'; |
||
40 | |||
41 | /** |
||
42 | * Compiler for stub file. |
||
43 | * |
||
44 | * @var StubFileCompiler |
||
45 | */ |
||
46 | protected $compiler; |
||
47 | |||
48 | /** |
||
49 | * Compiler for stub file. |
||
50 | * |
||
51 | * @var Filesystem |
||
52 | */ |
||
53 | protected $filesystem; |
||
54 | |||
55 | /** |
||
56 | * @var array |
||
57 | */ |
||
58 | protected static $lookup = [ |
||
59 | 'regular' => RegularRoute::class, |
||
60 | 'controller' => ControllerRoute::class, |
||
61 | 'resource' => ControllerResourceRoute::class, |
||
62 | ]; |
||
63 | |||
64 | /** |
||
65 | * The name and signature of the console command. |
||
66 | */ |
||
67 | protected $signature = 'make:route {link : The route link} {action? : View or controller to create} |
||
68 | {--t|type=regular : Type of route to create (regular,controller,resource)} {--m|method=get : HTTP method} |
||
69 | {--api : Route is an api route} {--a|createaction : Create view or controller after route} |
||
70 | {--menu : Create also menu entry using make:menu command} {--model : Create also a model using command make:model}'; |
||
71 | |||
72 | /** |
||
73 | * The console command description. |
||
74 | * |
||
75 | * @var string |
||
76 | */ |
||
77 | protected $description = 'Insert a route to routes/web.php file'; |
||
78 | |||
79 | /** |
||
80 | * AdminLTERoute constructor. |
||
81 | * |
||
82 | * @param StubFileCompiler $compiler |
||
83 | * @param Filesystem $filesystem |
||
84 | */ |
||
85 | public function __construct(StubFileCompiler $compiler, Filesystem $filesystem) |
||
86 | { |
||
87 | parent::__construct(); |
||
88 | $this->compiler = $compiler; |
||
89 | $this->filesystem = $filesystem; |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Execute the console command. |
||
94 | */ |
||
95 | public function handle() |
||
96 | { |
||
97 | $this->processInput(); |
||
98 | $this->warnIfRouteAlreadyExists($link = $this->argument('link')); |
||
99 | $tmpfile = $this->createTmpFileWithRoute(); |
||
100 | $path = $this->getPath($tmpfile); |
||
101 | add_file_into_file($this->mountpoint(), $path, $dstFile = $this->destinationFile()); |
||
102 | $this->info('Route ' . undot_path($link) . ' added to ' . $dstFile . '.'); |
||
103 | $this->postActions(); |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Get mountpoint. |
||
108 | * |
||
109 | * @return string |
||
110 | */ |
||
111 | protected function mountpoint() |
||
112 | { |
||
113 | if ($this->option('api')) { |
||
114 | return '#adminlte_api_routes'; |
||
115 | } |
||
116 | return '#adminlte_routes'; |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Destination route file. |
||
121 | * |
||
122 | * @return string |
||
123 | */ |
||
124 | protected function destinationFile() |
||
125 | { |
||
126 | if ($this->option('api')) { |
||
127 | return base_path($this->api_routes_path); |
||
128 | } |
||
129 | return base_path($this->web_routes_path); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Warn if route already exists. |
||
134 | * |
||
135 | * @param $link |
||
136 | */ |
||
137 | protected function warnIfRouteAlreadyExists($link) |
||
138 | { |
||
139 | if ($this->routeExists($link)) { |
||
140 | if ($this->confirm('Route already exists. Do you wish to continue?')) { |
||
141 | return; |
||
142 | } |
||
143 | die(); |
||
144 | } |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Check if route exists. |
||
149 | * |
||
150 | * @param $link |
||
151 | * @return mixed |
||
152 | */ |
||
153 | protected function routeExists($link) |
||
154 | { |
||
155 | if ($this->option('api')) { |
||
156 | return $this->apiRouteExists($link); |
||
157 | } |
||
158 | return $this->webRouteExists($link); |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Check if web route exists. |
||
163 | * |
||
164 | * @param $link |
||
165 | * @return mixed |
||
166 | */ |
||
167 | protected function webRouteExists($link) |
||
168 | { |
||
169 | $link = $this->removeTrailingSlashIfExists($link); |
||
170 | $link = $this->removeDuplicatedTrailingSlashes($link); |
||
171 | foreach (Route::getRoutes() as $value) { |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
172 | if (in_array(strtoupper($this->option('method')), array_merge($value->methods(), ['ANY'])) && |
||
173 | $value->uri() === $link) { |
||
174 | return true; |
||
175 | } |
||
176 | } |
||
177 | return false; |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Remove (if exists) trailing slash from link. |
||
182 | * |
||
183 | * @param $link |
||
184 | * @return string |
||
185 | */ |
||
186 | protected function removeTrailingSlashIfExists($link) |
||
187 | { |
||
188 | if (starts_with($link, '/')) { |
||
189 | return substr($link, 1); |
||
190 | } |
||
191 | return $link; |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Remove duplicated trailing slashes. |
||
196 | * |
||
197 | * @param $link |
||
198 | * @return mixed |
||
199 | */ |
||
200 | protected function removeDuplicatedTrailingSlashes($link) |
||
201 | { |
||
202 | return preg_replace('/(\/+)/', '/', $link); |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Check if api route exists. |
||
207 | * |
||
208 | * @param $link |
||
209 | * @return mixed |
||
210 | */ |
||
211 | protected function apiRouteExists($link) |
||
212 | { |
||
213 | return $this->webRouteExists('api/v1/' . $link); |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Crete tmp file with route to add. |
||
218 | * |
||
219 | * @return mixed |
||
220 | */ |
||
221 | protected function createTmpFileWithRoute() |
||
222 | { |
||
223 | $temp = tmpfile(); |
||
224 | fwrite($temp, $this->getRouteCode()); |
||
225 | return $temp; |
||
226 | } |
||
227 | |||
228 | /** |
||
229 | * Get path from file resource. |
||
230 | * |
||
231 | * @param $tmpfile |
||
232 | * @return mixed |
||
233 | */ |
||
234 | protected function getPath($tmpfile) |
||
235 | { |
||
236 | return stream_get_meta_data($tmpfile)['uri']; |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * Get route code to insert depending on type. |
||
241 | * |
||
242 | * @return mixed |
||
243 | */ |
||
244 | View Code Duplication | protected function getRouteCode() |
|
245 | { |
||
246 | $type = $this->option('type'); |
||
247 | $class = isset(static::$lookup[$type]) |
||
248 | ? static::$lookup[$type] |
||
249 | : RegularRoute::class; |
||
250 | /** @var GeneratesCode $route */ |
||
251 | $route = new $class($this->compiler, $this->filesystem); |
||
252 | $route->setReplacements([ |
||
253 | undot_path($this->argument('link')), |
||
254 | $this->action(), |
||
255 | $this->method() |
||
256 | ]); |
||
257 | return $route->code(); |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Get method. |
||
262 | * |
||
263 | * @return string |
||
264 | */ |
||
265 | View Code Duplication | protected function method() |
|
266 | { |
||
267 | if (strtolower($this->option('method')) == 'head') { |
||
268 | return 'get'; |
||
269 | } |
||
270 | return strtolower($this->option('method')); |
||
271 | } |
||
272 | |||
273 | /** |
||
274 | * Get the action replacement. |
||
275 | * |
||
276 | * @return array|string |
||
277 | */ |
||
278 | protected function action() |
||
279 | { |
||
280 | if ($this->argument('action') != null) { |
||
0 ignored issues
–
show
|
|||
281 | return $this->argument('action'); |
||
282 | } |
||
283 | if (strtolower($this->option('type')) != 'regular') { |
||
284 | return $this->argument('link') . 'Controller'; |
||
285 | } |
||
286 | return $this->argument('link'); |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Process input. |
||
291 | */ |
||
292 | protected function processInput() |
||
293 | { |
||
294 | $this->validateMethod(); |
||
295 | $this->validateType(); |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Validate option method. |
||
300 | */ |
||
301 | protected function validateMethod() |
||
302 | { |
||
303 | if (! in_array(strtoupper($this->option('method')), $methods = array_merge(Router::$verbs, ['ANY']))) { |
||
304 | throw new MethodNotAllowedException($methods); |
||
305 | } |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Validate option type. |
||
310 | */ |
||
311 | protected function validateType() |
||
312 | { |
||
313 | if (! in_array(strtolower($this->option('type')), ['regular','controller','resource'])) { |
||
314 | throw new RouteTypeNotValid(); |
||
315 | } |
||
316 | } |
||
317 | |||
318 | /** |
||
319 | * Execute post actions (if exists) |
||
320 | */ |
||
321 | protected function postActions() |
||
322 | { |
||
323 | if ($this->option('createaction') != null) { |
||
324 | $this->createAction(); |
||
325 | } |
||
326 | if ($this->option('menu') != null) { |
||
327 | $this->createMenu(); |
||
328 | } |
||
329 | if ($this->option('model') != null) { |
||
330 | $this->createModel($this->argument('link')); |
||
331 | } |
||
332 | } |
||
333 | |||
334 | /** |
||
335 | * Create menu. |
||
336 | */ |
||
337 | protected function createMenu() |
||
338 | { |
||
339 | try { |
||
340 | $this->warnIfSpatieMenuIsNotInstalled(); |
||
341 | } catch (\Exception $e) { |
||
342 | //Skip installation of menu |
||
343 | $this->error($e->getMessage()); |
||
344 | return; |
||
345 | } |
||
346 | Artisan::call('make:menu', [ |
||
347 | 'link' => $link = undot_path($this->argument('link')), |
||
348 | 'name' => ucfirst($link), |
||
349 | ]); |
||
350 | $this->info('Menu entry ' . $link .' added to config/menu.php file.'); |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * Warn if spatie menu ins not installed. |
||
355 | * |
||
356 | * @throws SpatieMenuDoesNotExists |
||
357 | */ |
||
358 | protected function warnIfSpatieMenuIsNotInstalled() |
||
359 | { |
||
360 | if (!(app()->getProvider('Spatie\Menu\Laravel\MenuServiceProvider'))) { |
||
361 | throw new SpatieMenuDoesNotExists(); |
||
362 | } |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Create action (view|controller). |
||
367 | */ |
||
368 | protected function createAction() |
||
369 | { |
||
370 | if (strtolower($this->option('type')) == 'regular' || $this->option('type') == null) { |
||
371 | return $this->createView(); |
||
372 | } |
||
373 | if (strtolower($this->option('type')) == 'controller') { |
||
374 | return $this->createController(); |
||
375 | } |
||
376 | return $this->createResourceController(); |
||
377 | } |
||
378 | |||
379 | /** |
||
380 | * Create View. |
||
381 | * |
||
382 | * @param null $name |
||
383 | */ |
||
384 | protected function createView($name = null) |
||
385 | { |
||
386 | if ($name == null) { |
||
387 | $name = $this->action(); |
||
388 | } |
||
389 | Artisan::call('make:view', [ |
||
390 | 'name' => $name |
||
391 | ]); |
||
392 | $this->info('View ' . undot_path($name) .'.blade.php created.'); |
||
393 | } |
||
394 | |||
395 | /** |
||
396 | * Create regular controller. |
||
397 | */ |
||
398 | protected function createController() |
||
399 | { |
||
400 | Artisan::call('make:controller', [ |
||
401 | 'name' => $controller = $this->controllerWithoutMethod($this->action()) |
||
402 | ]); |
||
403 | $this->addMethodToController($controller, $this->controllerMethod($this->action())); |
||
404 | $this->info('Controller ' . $controller .' created.'); |
||
405 | $this->createView($this->argument('link')); |
||
0 ignored issues
–
show
It seems like
$this->argument('link') targeting Illuminate\Console\Conce...ractsWithIO::argument() can also be of type array or string ; however, Acacha\AdminLTETemplateL...MakeRoute::createView() does only seem to accept null , maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
406 | } |
||
407 | |||
408 | /** |
||
409 | * Create resource controller. |
||
410 | */ |
||
411 | protected function createResourceController() |
||
412 | { |
||
413 | Artisan::call('make:controller', [ |
||
414 | 'name' => $controller = $this->controllerWithoutMethod($this->action()), |
||
415 | '--resource' => true |
||
416 | ]); |
||
417 | $this->info('Resource Controller ' . $controller .' created.'); |
||
418 | $this->createView($this->argument('link')); |
||
0 ignored issues
–
show
It seems like
$this->argument('link') targeting Illuminate\Console\Conce...ractsWithIO::argument() can also be of type array or string ; however, Acacha\AdminLTETemplateL...MakeRoute::createView() does only seem to accept null , maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Add method to controller. |
||
423 | * |
||
424 | * @param $controller |
||
425 | * @param $controllerMethod * |
||
426 | */ |
||
427 | protected function addMethodToController($controller, $controllerMethod) |
||
428 | { |
||
429 | $tmpfile = $this->createTmpFileWithMethod($controllerMethod); |
||
430 | $path = $this->getPath($tmpfile); |
||
431 | add_file_into_file('\/\/', $path, app_path('Http/Controllers/' . $controller . '.php')); |
||
432 | } |
||
433 | |||
434 | /** |
||
435 | * Crete tmp file with route to add. |
||
436 | * |
||
437 | * @param $controllerMethod |
||
438 | * @return mixed |
||
439 | */ |
||
440 | protected function createTmpFileWithMethod($controllerMethod) |
||
441 | { |
||
442 | $temp = tmpfile(); |
||
443 | fwrite($temp, $this->getMethodCode($controllerMethod)); |
||
444 | return $temp; |
||
445 | } |
||
446 | |||
447 | /** |
||
448 | * Get method code. |
||
449 | * |
||
450 | * @param $controllerMethod |
||
451 | * @return mixed |
||
452 | */ |
||
453 | protected function getMethodCode($controllerMethod) |
||
454 | { |
||
455 | return $this->compiler->compile( |
||
456 | $this->filesystem->get($this->getMethodStubPath()), |
||
457 | [ |
||
458 | 'METHOD' => $controllerMethod, |
||
459 | 'VIEW' => $this->argument('link') |
||
460 | ] |
||
461 | ); |
||
462 | } |
||
463 | |||
464 | /** |
||
465 | * Get method stub path. |
||
466 | * |
||
467 | * @return string |
||
468 | */ |
||
469 | protected function getMethodStubPath() |
||
470 | { |
||
471 | return __DIR__ . '/stubs/method.stub'; |
||
472 | } |
||
473 | } |
||
474 |