RouteListCommand::isGeoRoute()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 9
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace LaraCrafts\GeoRoutes\Console\Commands;
4
5
use Illuminate\Foundation\Console\RouteListCommand as BaseCommand;
6
use Illuminate\Routing\Route;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Facades\Validator;
9
use Symfony\Component\Console\Input\InputOption;
10
11
class RouteListCommand extends BaseCommand
12
{
13
    /**
14
     * The console command name.
15
     *
16
     * @var string
17
     */
18
    protected $name = 'route:list';
19
20
    /**
21
     * The console command description.
22
     *
23
     * @var string
24
     */
25
    protected $description = 'List all registered routes';
26
27
    /**
28
     * The router instance.
29
     *
30
     * @var \Illuminate\Routing\Router
31
     */
32
    protected $router;
33
34
    /**
35
     * The table geo headers for the command.
36
     *
37
     * @var array
38
     */
39
    protected $geoHeaders = ['Countries', 'Strategy', 'Callback'];
40
41
    /**
42
     * The columns to display when using the "compact" flag.
43
     *
44
     * @var array
45
     */
46
    protected $compactColumns = ['method', 'uri', 'action'];
47
48
    /**
49
     * Get the route information for a given route.
50
     *
51
     * @param  \Illuminate\Routing\Route  $route
52
     * @return array
53
     */
54 64
    protected function getRouteInformation(Route $route)
55
    {
56 64
        return $this->filterRoute([
57 64
            'domain' => $route->domain(),
58 64
            'method' => implode('|', $route->methods()),
59 64
            'uri'    => $route->uri(),
60 64
            'name'   => $route->getName(),
61 64
            'action' => ltrim($route->getActionName(), '\\'),
62 64
            'middleware' => $this->getMiddleware($route),
63 64
            'is_geo' => $this->isGeoRoute($route),
64 64
            'countries' => $this->getCountries($route),
65 64
            'strategy' => $this->getStrategy($route),
66 64
            'callback' => $this->getCallback($route),
67
        ]);
68
    }
69
70
    /**
71
     * Display the route information on the console.
72
     *
73
     * @param  array  $routes
74
     * @return void
75
     */
76 64
    protected function displayRoutes(array $routes)
77
    {
78 64
        if ($this->hasOption('json') && $this->option('json')) {
79
            $this->line(json_encode(array_values($routes)));
80
81
            return;
82
        }
83
        
84 64
        $this->table($this->getHeaders(), $this->formatRoutes($routes));
85 64
    }
86
87
    /**
88
     * Format the routes output.
89
     *
90
     * @param array $routes
91
     *
92
     * @return array
93
     */
94 64
    protected function formatRoutes(array $routes)
95
    {
96 64
        foreach ($routes as $key => $route) {
97 64
            $routes[$key]['countries'] = $this->formatCountries($route['countries']);
98 64
            $routes[$key]['strategy'] = $this->formatStrategy($route['strategy']);
99 64
            $routes[$key]['callback'] = $this->formatCallback($route['callback']);
100
        }
101
102 64
        return $routes;
103
    }
104
105
    /**
106
     * Filter the route by the coutnry, strategy,
107
     * URI or/and name
108
     *
109
     * @param  array  $route
110
     *
111
     * @return array|null
112
     */
113 64
    protected function filterRoute(array $route)
114
    {
115 64
        if (($this->option('country') && !in_array(strtoupper($this->option('country')), $route['countries'] ?? []))
0 ignored issues
show
Bug introduced by
It seems like $this->option('country') can also be of type string[]; however, parameter $string of strtoupper() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

115
        if (($this->option('country') && !in_array(strtoupper(/** @scrutinizer ignore-type */ $this->option('country')), $route['countries'] ?? []))
Loading history...
116 64
            || $this->option('strategy') && $route['strategy'] != strtolower($this->option('strategy'))
0 ignored issues
show
Bug introduced by
It seems like $this->option('strategy') can also be of type string[]; however, parameter $str of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

116
            || $this->option('strategy') && $route['strategy'] != strtolower(/** @scrutinizer ignore-type */ $this->option('strategy'))
Loading history...
117 64
            || $this->option('geo-only') && !$route['is_geo']) {
118 48
            return;
119
        }
120
121 64
        return parent::filterRoute($route);
122
    }
123
124
    /**
125
     * Get the table headers for the visible columns.
126
     *
127
     * @return array
128
     */
129 64
    protected function getHeaders()
130
    {
131 64
        return Arr::only(
132 64
            $this->hasGeoOption() ? array_merge($this->headers, $this->geoHeaders) : $this->headers,
133 64
            array_keys($this->getColumns())
134
        );
135
    }
136
137
    /**
138
     * Get the column names to show (lowercase table headers).
139
     *
140
     * @return array
141
     */
142 64
    protected function getColumns()
143
    {
144 64
        $availableColumns = array_map(
145 64
            'strtolower',
146 64
            $this->hasGeoOption() ? array_merge($this->headers, $this->geoHeaders) : $this->headers
147
        );
148
149 64
        if ($this->hasOption('compact') && $this->option('compact')) {
150
            return array_intersect($availableColumns, $this->compactColumns);
151
        }
152
153 64
        if ($this->hasOption('columns') && $columns = $this->option('columns')) {
154
            return array_intersect($availableColumns, $this->parseColumns($columns));
0 ignored issues
show
Bug introduced by
It seems like $columns can also be of type string and true; however, parameter $columns of Illuminate\Foundation\Co...Command::parseColumns() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

154
            return array_intersect($availableColumns, $this->parseColumns(/** @scrutinizer ignore-type */ $columns));
Loading history...
155
        }
156
157 64
        return $availableColumns;
158
    }
159
160
    /**
161
     * Determine if the given route is a georoute.
162
     *
163
     * @param \Illuminate\Routing\Route $route
164
     *
165
     * @return boolean
166
     */
167 64
    protected function isGeoRoute(Route $route)
168
    {
169 64
        $validator = Validator::make($route->getAction('geo') ?? [], [
170 64
            'countries' => 'required|array|min:1',
171
            'countries.*' => 'string|min:2|max:2',
172
            'strategy' => 'required|in:allow,deny',
173
        ]);
174
175 64
        return $validator->passes();
176
    }
177
178
    /**
179
     * Get the list of countries covered by
180
     * the geo-constraint for the given route.
181
     *
182
     * @param \Illuminate\Routing\Route $route
183
     *
184
     * @return array|null
185
     */
186 64
    protected function getCountries(Route $route)
187
    {
188 64
        return $route->getAction('geo')['countries'];
189
    }
190
191
    /**
192
     * Get the route geo strategy.
193
     *
194
     * @param \Illuminate\Routing\Route $route
195
     *
196
     * @return string|null
197
     */
198 64
    protected function getStrategy(Route $route)
199
    {
200 64
        return $route->getAction('geo')['strategy'];
201
    }
202
203
    /**
204
     * Get the route geo callback.
205
     *
206
     * @param \Illuminate\Routing\Route $route
207
     *
208
     * @return string|null
209
     */
210 64
    protected function getCallback(Route $route)
211
    {
212 64
        return $route->getAction('geo')['callback'][0];
213
    }
214
    
215
    /**
216
     * Format the route strategy output.
217
     *
218
     * @param string|null $strategy
219
     *
220
     * @return string
221
     */
222 64
    protected function formatStrategy($strategy)
223
    {
224 64
        $strategy = strtolower($strategy);
225
226 64
        if ($strategy == 'allow') {
227 48
            return '<fg=green;options=bold>Allow</>';
228
        }
229
230 64
        if ($strategy == 'deny') {
231 64
            return '<fg=red;options=bold>Deny</>';
232
        }
233
234 16
        return '<fg=yellow>None</>';
235
    }
236
237
    /**
238
     * Format the route countries output.
239
     *
240
     * @param array|null $countries
241
     *
242
     * @return string
243
     */
244 64
    protected function formatCountries($countries)
245
    {
246 64
        return $countries ? implode(', ', $countries) : '<fg=yellow>None</>';
247
    }
248
249
    /**
250
     * Format the route callback output.
251
     *
252
     * @param string|null $callback
253
     *
254
     * @return string
255
     */
256 64
    protected function formatCallback($callback)
257
    {
258 64
        return !is_null($callback) ? str_replace('::', '@', $callback) : '<fg=yellow>None</>';
259
    }
260
261
    /**
262
     * Determine if any geo option exists.
263
     *
264
     * @return boolean
265
     */
266 64
    protected function hasGeoOption()
267
    {
268 64
        return $this->option('geo') || $this->option('geo-only')
269 64
            || $this->option('country') || $this->option('strategy');
270
    }
271
272
    /**
273
     * Get the console command options.
274
     *
275
     * @return array
276
     */
277 64
    protected function getOptions()
278
    {
279 64
        return array_merge(parent::getOptions(), [
280 64
            ['geo', 'g', InputOption::VALUE_NONE, 'Show the routes geo specifications'],
281 64
            ['geo-only', null, InputOption::VALUE_NONE, 'Display GeoRoutes only'],
282 64
            ['strategy', null, InputOption::VALUE_REQUIRED, 'Display only the routes that have a given strategy'],
283 64
            ['country', null, InputOption::VALUE_REQUIRED, 'Display only the routes that have a given country'],
284
        ]);
285
    }
286
}
287