Skip to content
This repository was archived by the owner on Feb 13, 2022. It is now read-only.

Commit 0d2e9dd

Browse files
committed
Command to check routes for invalid actions
1 parent d657ad1 commit 0d2e9dd

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed

src/Commands/CheckRoutes.php

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
namespace Shift\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Contracts\Container\BindingResolutionException;
7+
use Illuminate\Routing\Route;
8+
use Illuminate\Support\Collection;
9+
use Illuminate\Support\Str;
10+
use ReflectionException;
11+
use ReflectionMethod;
12+
13+
class CheckRoutes extends Command
14+
{
15+
/**
16+
* The name and signature of the console command.
17+
*
18+
* @var string
19+
*/
20+
protected $signature = 'shift:check-routes';
21+
22+
/**
23+
* The console command description.
24+
*
25+
* @var string
26+
*/
27+
protected $description = 'Find routes which do not have a corresponding controller action';
28+
29+
/**
30+
* Create a new command instance.
31+
*
32+
* @return void
33+
*/
34+
public function __construct()
35+
{
36+
parent::__construct();
37+
}
38+
39+
/**
40+
* Execute the console command.
41+
*
42+
* @return mixed
43+
*/
44+
public function handle()
45+
{
46+
collect(\Illuminate\Support\Facades\Route::getRoutes())
47+
->filter(function (Route $route) {
48+
return is_string($route->getAction('uses'));
49+
})
50+
->map(function (Route $route) {
51+
try {
52+
$controller = $route->getController();
53+
$method = Str::parseCallback($route->getAction('uses'), '__invoke')[1];
54+
55+
if (is_null($method)) {
56+
return [
57+
'type' => 'undefined',
58+
'action' => $route->getActionName()
59+
];
60+
}
61+
62+
$reflectedMethod = new ReflectionMethod($controller, $method);
63+
if ($reflectedMethod->isPublic()) {
64+
return null;
65+
}
66+
67+
return [
68+
'type' => 'visibility',
69+
'action' => $route->getActionName()
70+
];
71+
} catch (BindingResolutionException $exception) {
72+
return [
73+
'type' => 'controller',
74+
'action' => $route->getActionName()
75+
];
76+
} catch (ReflectionException $exception) {
77+
return [
78+
'type' => 'method',
79+
'action' => $route->getActionName()
80+
];
81+
}
82+
})
83+
->filter()
84+
->mapToGroups(function ($error) {
85+
return [$error['type'] => $error['action']];
86+
})
87+
->sortBy('type')
88+
->each(function ($actions, $type) {
89+
$this->displayHeader($type);
90+
$this->displayIssues($actions);
91+
});
92+
}
93+
94+
private function displayHeader($type)
95+
{
96+
if ($type === 'controller') {
97+
$this->output->error('Undefined Controllers');
98+
$this->output->text([
99+
'The following actions referenced controllers which do not exist. To resolve, quickly create these controllers using `artisan make:controller` or remove these routes.'
100+
]);
101+
} elseif ($type === 'method') {
102+
$this->output->warning('Undefined Methods');
103+
$this->output->text([
104+
'The following actions referenced a method in the controller which did not exist. To resolve, you may add the method to the controller or remove these routes.'
105+
]);
106+
} else {
107+
$this->output->note('Incorrect Visibility');
108+
$this->output->text([
109+
'The following actions referenced methods which existed, but have the incorrect visibility. To resolve, you may update the method visibility to `public` or remove these routes.'
110+
]);
111+
}
112+
113+
$this->output->newLine();
114+
}
115+
116+
private function displayIssues(Collection $actions)
117+
{
118+
$this->output->listing($actions->toArray());
119+
$this->output->newLine();
120+
}
121+
}

src/ServiceProvider.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Shift;
4+
5+
use Illuminate\Contracts\Support\DeferrableProvider;
6+
7+
class ServiceProvider extends \Illuminate\Support\ServiceProvider implements DeferrableProvider
8+
{
9+
/**
10+
* Bootstrap the application events.
11+
*
12+
* @return void
13+
*/
14+
public function boot()
15+
{
16+
//
17+
}
18+
19+
/**
20+
* Register the service provider.
21+
*
22+
* @return void
23+
*/
24+
public function register()
25+
{
26+
if ($this->app->runningInConsole()) {
27+
$this->commands([
28+
\Shift\Commands\CheckRoutes::class,
29+
]);
30+
}
31+
}
32+
33+
/**
34+
* Get the services provided by the provider.
35+
*
36+
* @return array
37+
*/
38+
public function provides()
39+
{
40+
return [
41+
\Shift\Commands\CheckRoutes::class,
42+
];
43+
}
44+
}

0 commit comments

Comments
 (0)