Issues (11)

src/Debug/DebugRoutesCommand.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Router\Debug;
6
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Helper\Table;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
use Symfony\Component\Console\Style\SymfonyStyle;
13
use Yiisoft\Router\RouteCollectionInterface;
14
use Yiisoft\VarDumper\VarDumper;
15
use Yiisoft\Yii\Debug\Debugger;
16
17
final class DebugRoutesCommand extends Command
18
{
19
    public const COMMAND_NAME = 'debug:routes';
20
    protected static $defaultName = self::COMMAND_NAME;
21
22 2
    public function __construct(
23
        private RouteCollectionInterface $routeCollection,
24
        private Debugger $debugger,
25
    ) {
26 2
        parent::__construct();
27
    }
28
29 2
    protected function configure(): void
30
    {
31 2
        $this
32 2
            ->setDescription('Show information about registered routes')
33 2
            ->addArgument('route', InputArgument::IS_ARRAY, 'Route name');
34
    }
35
36
    /**
37
     * @psalm-suppress MixedArgument, MixedAssignment, MixedArrayAccess
38
     */
39 2
    protected function execute(InputInterface $input, OutputInterface $output): int
40
    {
41 2
        $this->debugger->stop();
42
43 2
        $io = new SymfonyStyle($input, $output);
44
45 2
        if ($input->hasArgument('route') && !empty($input->getArgument('route'))) {
46
            /**
47
             * @var string[] $routes
48
             */
49 1
            $routes = (array) $input->getArgument('route');
50 1
            foreach ($routes as $route) {
51 1
                $route = $this->routeCollection->getRoute($route);
52 1
                $data = $route->__debugInfo();
53 1
                $action = '';
54 1
                $middlewares = [];
55 1
                if (!empty($data['enabledMiddlewares'])) {
56 1
                    $middlewareDefinitions = $data['enabledMiddlewares'];
57 1
                    $action = array_pop($middlewareDefinitions);
58 1
                    $middlewares = $middlewareDefinitions;
59
                }
60
61 1
                $io->title($data['name']);
0 ignored issues
show
It seems like $data['name'] can also be of type null; however, parameter $message of Symfony\Component\Consol...e\SymfonyStyle::title() 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

61
                $io->title(/** @scrutinizer ignore-type */ $data['name']);
Loading history...
62 1
                $definitionList = [
63 1
                    ['Methods' => $this->export($data['methods'])],
64 1
                    ['Name' => $data['name']],
65 1
                    ['Pattern' => $data['pattern']],
66 1
                ];
67 1
                if (!empty($action)) {
68 1
                    $definitionList[] = ['Action' => $this->export($action)];
69
                }
70 1
                if (!empty($data['defaults'])) {
71 1
                    $definitionList[] = ['Defaults' => $this->export($data['defaults'])];
72
                }
73 1
                if (!empty($data['hosts'])) {
74 1
                    $definitionList[] = ['Hosts' => $this->export($data['hosts'])];
75
                }
76
77 1
                $io->definitionList(...$definitionList);
78 1
                if (!empty($middlewares)) {
79 1
                    $io->section('Middlewares');
80 1
                    foreach ($middlewares as $middleware) {
81 1
                        $io->writeln(is_string($middleware) ? $middleware : $this->export($middleware));
82
                    }
83
                }
84
            }
85
86 1
            return 0;
87
        }
88
89 1
        $table = new Table($output);
90 1
        $rows = [];
91 1
        foreach ($this->routeCollection->getRoutes() as $route) {
92 1
            $data = $route->__debugInfo();
93 1
            $action = '';
94 1
            if (!empty($data['enabledMiddlewares'])) {
95 1
                $middlewareDefinitions = $data['enabledMiddlewares'];
96 1
                $action = array_pop($middlewareDefinitions);
97
            }
98 1
            $rows[] = [
99 1
                'methods' => $this->export($data['methods']),
100 1
                'name' => $data['name'],
101 1
                'hosts' => $this->export($data['hosts']),
102 1
                'pattern' => $data['pattern'],
103 1
                'defaults' => $this->export($data['defaults']),
104 1
                'action' => $this->export($action),
105 1
            ];
106
        }
107 1
        $table->addRows($rows);
108 1
        $table->render();
109
110 1
        return 0;
111
    }
112
113 2
    protected function export(mixed $value): string
114
    {
115 2
        if (is_array($value)
116 2
            && count($value) === 2
117 2
            && isset($value[0], $value[1])
118 2
            && is_string($value[0])
119 2
            && is_string($value[1])
120
        ) {
121 1
            return $value[0] . '::' . $value[1];
122
        }
123 2
        if (is_array($value) && $this->isArrayList($value)) {
124 2
            return implode(', ', array_map(fn ($item) => $this->export($item), $value));
125
        }
126 2
        if (is_string($value)) {
127 2
            return $value;
128
        }
129 2
        return VarDumper::create($value)->asString();
130
    }
131
132
    /**
133
     * Polyfill for is_array_list() function.
134
     * It is available since PHP 8.1.
135
     */
136 2
    private function isArrayList(array $array): bool
137
    {
138 2
        if ([] === $array) {
139 1
            return true;
140
        }
141
142 2
        $nextKey = -1;
143
144 2
        foreach ($array as $k => $_) {
145 2
            if ($k !== ++$nextKey) {
146 2
                return false;
147
            }
148
        }
149
150 2
        return true;
151
    }
152
}
153