Passed
Branch master (e894a3)
by Melech
15:39 queued 01:19
created

RoutesList::run()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 60
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 44
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 60
rs 9.216

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Valkyrja\Http\Routing\Command;
15
16
use InvalidArgumentException;
17
use Valkyrja\Console\Commander\Commander;
18
use Valkyrja\Console\Enum\FormatForeground;
19
use Valkyrja\Console\Input\Contract\Input as InputContract;
20
use Valkyrja\Console\Input\Input;
21
use Valkyrja\Console\Output\Contract\Output as OutputContract;
22
use Valkyrja\Console\Output\Output;
23
use Valkyrja\Console\Support\Provides;
24
use Valkyrja\Http\Routing\Contract\Router;
25
use Valkyrja\Http\Routing\Model\Contract\Route;
26
27
use function implode;
28
use function max;
29
use function str_repeat;
30
use function strlen;
31
use function usort;
32
33
/**
34
 * Class RoutesList.
35
 *
36
 * @author Melech Mizrachi
37
 */
38
class RoutesList extends Commander
39
{
40
    use Provides;
41
42
    /** @var string */
43
    public const string COMMAND = 'routes:list';
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_STRING, expecting '=' on line 43 at column 24
Loading history...
44
    /** @var string */
45
    public const string PATH = self::COMMAND;
46
    /** @var string */
47
    public const string SHORT_DESCRIPTION = 'List all routes';
48
    /** @var string */
49
    public const string DESCRIPTION = '';
50
51
    /** @var string */
52
    protected const string INVERT_FORMAT = "\e[7m";
53
    /** @var string */
54
    protected const string END_FORMAT = "\e[0m";
55
56
    public function __construct(
57
        protected Router $router,
58
        InputContract $input = new Input(),
59
        OutputContract $output = new Output()
60
    ) {
61
        parent::__construct($input, $output);
62
    }
63
64
    /**
65
     * @inheritDoc
66
     *
67
     * @throws InvalidArgumentException
68
     */
69
    public function run(): int
70
    {
71
        $routerRoutes = $this->router->getRoutes();
72
        $routes       = [];
73
        $headerTexts  = [
74
            'Request Methods',
75
            'Path',
76
            'Name',
77
            'Dispatch',
78
            'Regex',
79
        ];
80
        $lengths      = [
81
            strlen($headerTexts[0]),
82
            strlen($headerTexts[1]),
83
            strlen($headerTexts[2]),
84
            strlen($headerTexts[3]),
85
            strlen($headerTexts[4]),
86
        ];
87
88
        // Sort routes by path
89
        usort($routerRoutes, static fn (Route $a, Route $b) => $a->getPath() <=> $b->getPath());
90
91
        foreach ($routerRoutes as $route) {
92
            $routes[] = $this->setRoute($route, $lengths);
93
        }
94
95
        $sepLine = $this->getSepLine($lengths);
96
        $odd     = false;
97
98
        $this->output->writeMessage($this->oddFormat(true) . $sepLine, true);
99
        $this->headerMessage($headerTexts, $lengths);
100
        $this->output->writeMessage($sepLine, true);
101
102
        foreach ($routes as $key => $route) {
103
            $routeMessage = '| '
104
                . $route[0]
105
                . str_repeat(' ', $lengths[0] - strlen($route[0]))
106
                . ' | '
107
                . $route[1]
108
                . str_repeat(' ', $lengths[1] - strlen($route[1]))
109
                . ' | '
110
                . $route[2]
111
                . str_repeat(' ', $lengths[2] - strlen($route[2]))
112
                . ' | '
113
                . $route[3]
114
                . str_repeat(' ', $lengths[3] - strlen($route[3]))
115
                . ' | '
116
                . $route[4]
117
                . str_repeat(' ', $lengths[4] - strlen($route[4]))
118
                . ' |';
119
120
            $odd          = $key % 2 > 0;
121
            $routeMessage = $this->oddFormat($odd) . $routeMessage;
122
123
            $this->output->writeMessage($routeMessage . static::END_FORMAT, true);
124
        }
125
126
        $this->output->writeMessage($this->oddFormat(! $odd) . $sepLine . static::END_FORMAT, true);
127
128
        return 0;
129
    }
130
131
    /**
132
     * Set a route as an array from a route object.
133
     *
134
     * @param Route           $route   The route object
135
     * @param array<int, int> $lengths The longest string lengths
136
     *
137
     * @throws InvalidArgumentException
138
     *
139
     * @return array{0: string, 1: string, 2: string, 3: string, 4: string}
140
     */
141
    protected function setRoute(Route $route, array &$lengths): array
142
    {
143
        $requestMethod = implode(' | ', array_column($route->getMethods(), 'value'));
144
        $dispatch      = 'Closure';
145
        $regex         = $route->getRegex() ?? '';
146
        $path          = $route->getPath();
147
        $name          = $route->getName() ?? '';
148
149
        if ($requestMethod === 'GET | HEAD | POST | PUT | PATCH | CONNECT | OPTIONS | TRACE | DELETE') {
150
            $requestMethod = 'ANY';
151
        }
152
153
        if (($function = $route->getFunction()) !== null) {
154
            $dispatch = $function;
155
        } elseif (null !== $class = $route->getClass()) {
156
            $dispatch = $class
157
                . ($route->isStatic() ? '::' : '->')
158
                . ((($method = $route->getMethod()) !== null)
159
                    ? $method . '()'
160
                    : $route->getProperty() ?? '');
161
        }
162
163
        $lengths[0] = max($lengths[0], strlen($requestMethod));
164
        $lengths[1] = max($lengths[1], strlen($path));
165
        $lengths[2] = max($lengths[2], strlen($name));
166
        $lengths[3] = max($lengths[3], strlen($dispatch));
167
        $lengths[4] = max($lengths[4], strlen($regex));
168
169
        return [
170
            $requestMethod,
171
            $path,
172
            $name,
173
            $dispatch,
174
            $regex,
175
        ];
176
    }
177
178
    /**
179
     * Get the separation line.
180
     *
181
     * @param array<int, int> $lengths The longest lengths
182
     *
183
     * @return string
184
     */
185
    protected function getSepLine(array $lengths): string
186
    {
187
        return '+-' . str_repeat('-', $lengths[0])
188
            . '-+-' . str_repeat('-', $lengths[1])
189
            . '-+-' . str_repeat('-', $lengths[2])
190
            . '-+-' . str_repeat('-', $lengths[3])
191
            . '-+-' . str_repeat('-', $lengths[4])
192
            . '-+';
193
    }
194
195
    /**
196
     * Format odd rows.
197
     *
198
     * @param bool $odd
199
     *
200
     * @return string
201
     */
202
    protected function oddFormat(bool $odd): string
203
    {
204
        return $odd
205
            ? static::INVERT_FORMAT . "\e[" . ((string) FormatForeground::CYAN->value) . 'm'
206
            : static::INVERT_FORMAT . "\e[" . ((string) FormatForeground::LIGHT_CYAN->value) . 'm';
207
    }
208
209
    /**
210
     * Output the header message.
211
     *
212
     * @param array<int, string> $headerTexts The header texts
213
     * @param array<int, int>    $lengths     The longest lengths
214
     *
215
     * @return void
216
     */
217
    protected function headerMessage(array $headerTexts, array $lengths): void
218
    {
219
        $headerMessage = '| ' . $headerTexts[0]
220
            . str_repeat(' ', $lengths[0] - strlen($headerTexts[0]))
221
            . ' | ' . $headerTexts[1]
222
            . str_repeat(' ', $lengths[1] - strlen($headerTexts[1]))
223
            . ' | ' . $headerTexts[2]
224
            . str_repeat(' ', $lengths[2] - strlen($headerTexts[2]))
225
            . ' | ' . $headerTexts[3]
226
            . str_repeat(' ', $lengths[3] - strlen($headerTexts[3]))
227
            . ' | ' . $headerTexts[4]
228
            . str_repeat(' ', $lengths[4] - strlen($headerTexts[4]))
229
            . ' |';
230
231
        $this->output->writeMessage($headerMessage, true);
232
    }
233
}
234