Passed
Push — master ( c2770c...1d5b12 )
by Anton
04:44 queued 02:18
created

DebugCommand::perform()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 5
c 2
b 0
f 1
dl 0
loc 11
rs 10
cc 3
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Command\Router;
6
7
use Spiral\Console\Command;
8
use Spiral\Core\Container\SingletonInterface;
9
use Spiral\Router\Route;
10
use Spiral\Router\RouterInterface;
11
use Spiral\Router\Target\Action;
12
use Symfony\Component\Console\Helper\Table;
13
14
class DebugCommand extends Command implements SingletonInterface
15
{
16
    protected const NAME = 'route:list';
17
    protected const DESCRIPTION = 'List application routes';
18
19
    /**
20
     * @param RouterInterface $router
21
     */
22
    public function perform(RouterInterface $router): void
23
    {
24
        $grid = $this->table(['Verbs:', 'Pattern:', 'Target:']);
25
26
        foreach ($this->getRoutes($router) as $name => $route) {
27
            if ($route instanceof Route) {
28
                $this->renderRoute($grid, $name, $route);
29
            }
30
        }
31
32
        $grid->render();
33
    }
34
35
    /**
36
     * @param Table $table
37
     * @param string $name
38
     * @param Route $route
39
     */
40
    private function renderRoute(Table $table, string $name, Route $route)
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed. ( Ignorable by Annotation )

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

40
    private function renderRoute(Table $table, /** @scrutinizer ignore-unused */ string $name, Route $route)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
41
    {
42
        $table->addRow(
43
            [
44
                $this->getVerbs($route),
45
                $this->getPattern($route),
46
                $this->getTarget($route)
47
            ]
48
        );
49
    }
50
51
    /**
52
     * @param RouterInterface $router
53
     * @return \Generator|null
54
     */
55
    private function getRoutes(RouterInterface $router): ?\Generator
56
    {
57
        yield from $router->getRoutes();
58
    }
59
60
    /**
61
     * @param Route $route
62
     * @return string
63
     */
64
    private function getVerbs(Route $route): string
65
    {
66
        $result = [];
67
68
        foreach ($route->getVerbs() as $verb) {
69
            switch (strtolower($verb)) {
70
                case 'get':
71
                    $verb = '<fg=green>GET</>';
72
                    break;
73
                case 'post':
74
                    $verb = '<fg=blue>POST</>';
75
                    break;
76
                case 'put':
77
                    $verb = '<fg=yellow>PUT</>';
78
                    break;
79
                case 'delete':
80
                    $verb = '<fg=red>DELETE</>';
81
                    break;
82
            }
83
84
            $result[] = $verb;
85
        }
86
87
        return implode(', ', $result);
88
    }
89
90
    /**
91
     * @param Route $route
92
     * @return string
93
     */
94
    private function getPattern(Route $route): string
95
    {
96
        $pattern = $this->getValue($route->getUriHandler(), 'pattern');
97
        $pattern = str_replace(
98
            '[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}',
99
            'uuid',
100
            $pattern
101
        );
102
103
        return preg_replace_callback(
104
            '/<([^>]*)>/',
105
            static function ($m) {
106
                return sprintf('<fg=yellow>%s</>', $m[0]);
107
            },
108
            $pattern
109
        );
110
    }
111
112
    /**
113
     * @param Route $route
114
     * @return string
115
     */
116
    private function getTarget(Route $route): string
117
    {
118
        $target = $this->getValue($route, 'target');
119
        switch (true) {
120
            case $target instanceof Action:
121
                return sprintf(
122
                    '%s::%s',
123
                    $this->getValue($target, 'controller'),
124
                    $this->getValue($target, 'action')
125
                );
126
        }
127
128
        return '';
129
        return $this->getValue($route->getUriHandler(), 'pattern');
0 ignored issues
show
Unused Code introduced by
return $this->getValue($...riHandler(), 'pattern') is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
130
    }
131
132
    /**
133
     * @param object $object
134
     * @param string $property
135
     * @return mixed
136
     */
137
    private function getValue(object $object, string $property)
138
    {
139
        try {
140
            $r = new \ReflectionObject($object);
141
            $prop = $r->getProperty($property);
142
            $prop->setAccessible(true);
143
        } catch (\Throwable $e) {
144
            return $e->getMessage();
145
        }
146
147
        return $prop->getValue($object);
148
    }
149
}
150