Passed
Pull Request — master (#831)
by Maxim
11:02 queued 04:50
created

RouteGroup::setNamePrefix()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Router;
6
7
use Psr\Container\ContainerInterface;
8
use Psr\Http\Server\MiddlewareInterface;
9
use Spiral\Core\BinderInterface;
10
use Spiral\Core\Container\Autowire;
11
use Spiral\Core\CoreInterface;
12
use Spiral\Http\Pipeline;
13
use Spiral\Router\Target\AbstractTarget;
14
15
/**
16
 * RouteGroup provides the ability to configure multiple routes to controller/actions using same presets.
17
 */
18
final class RouteGroup
19
{
20
    private string $prefix = '';
21
    private string $namePrefix = '';
22
23
    /** @var string[] */
24
    private array $routes = [];
25
26
    /** @var array<class-string<MiddlewareInterface>|MiddlewareInterface|Autowire> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string<Middl...wareInterface|Autowire> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string<MiddlewareInterface>|MiddlewareInterface|Autowire>.
Loading history...
27
    private array $middleware = [];
28
29
    private ?CoreInterface $core = null;
30
31 285
    public function __construct(
32
        private readonly ContainerInterface $container,
33
        private readonly RouterInterface $router,
34
        private readonly UriHandler $handler,
35
        private readonly ?string $name = null
36
    ) {
37
    }
38
39
    /**
40
     * Check if group has a route with given name
41
     */
42 4
    public function hasRoute(string $name): bool
43
    {
44 4
        return \in_array($name, $this->routes);
45
    }
46
47
    /**
48
     * Prefix added to all the routes.
49
     */
50 267
    public function setPrefix(string $prefix): self
51
    {
52 267
        $this->prefix = $prefix;
53
54
        // update routes
55 267
        $this->flushRoutes();
56
57 267
        return $this;
58
    }
59
60
    /**
61
     * Route name prefix added to all routes.
62
     */
63 1
    public function setNamePrefix(string $prefix): self
64
    {
65 1
        $this->namePrefix = $prefix;
66
67
        // update routes
68 1
        $this->flushRoutes();
69
70 1
        return $this;
71
    }
72
73 2
    public function setCore(Autowire|CoreInterface|string $core): self
74
    {
75 2
        if (!$core instanceof CoreInterface) {
76 1
            $core = $this->container->get($core);
0 ignored issues
show
Bug introduced by
It seems like $core can also be of type Spiral\Core\Container\Autowire; however, parameter $id of Psr\Container\ContainerInterface::get() 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

76
            $core = $this->container->get(/** @scrutinizer ignore-type */ $core);
Loading history...
77
        }
78 2
        $this->core = $core;
79
80
        // update routes
81 2
        $this->flushRoutes();
82
83 2
        return $this;
84
    }
85
86
    /**
87
     * @param MiddlewareInterface|Autowire|class-string<MiddlewareInterface>|non-empty-string $middleware
0 ignored issues
show
Documentation Bug introduced by
The doc comment MiddlewareInterface|Auto...rface>|non-empty-string at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in MiddlewareInterface|Autowire|class-string<MiddlewareInterface>|non-empty-string.
Loading history...
88
     */
89 271
    public function addMiddleware(MiddlewareInterface|Autowire|string $middleware): self
90
    {
91 271
        $this->middleware[] = $middleware;
92
93 271
        if ($this->container instanceof BinderInterface && $this->name !== null) {
94 271
            $this->container->bind(
0 ignored issues
show
Bug introduced by
The method bind() does not exist on Psr\Container\ContainerInterface. It seems like you code against a sub-type of Psr\Container\ContainerInterface such as Spiral\Core\Container. ( Ignorable by Annotation )

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

94
            $this->container->/** @scrutinizer ignore-call */ 
95
                              bind(
Loading history...
95 271
                'middleware:' . $this->name,
96 271
                function (PipelineFactory $factory): Pipeline {
97 271
                    return $factory->createWithMiddleware($this->middleware);
98
                }
99
            );
100
        }
101
102
        // update routes
103 271
        $this->flushRoutes();
104
105 271
        return $this;
106
    }
107
108
    /**
109
     * Push routes to router.
110
     *
111
     * @internal
112
     */
113 274
    public function flushRoutes(): void
114
    {
115 274
        foreach ($this->routes as $name) {
116 267
            $this->router->setRoute($name, $this->applyGroupParams($this->router->getRoute($name)));
117
        }
118
    }
119
120
    /**
121
     * Add a route to a route group.
122
     */
123 284
    public function addRoute(string $name, Route $route): self
124
    {
125 284
        if ($this->name !== null && $this->middleware !== []) {
126 271
            $route = $route->withMiddleware('middleware:' . $this->name);
0 ignored issues
show
Bug introduced by
'middleware:' . $this->name of type string is incompatible with the type Spiral\Router\Traits\MiddlewareType|array expected by parameter $middleware of Spiral\Router\Route::withMiddleware(). ( Ignorable by Annotation )

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

126
            $route = $route->withMiddleware(/** @scrutinizer ignore-type */ 'middleware:' . $this->name);
Loading history...
127
        }
128
129 284
        $this->routes[] = $this->namePrefix . $name;
130
131 284
        $this->router->setRoute($this->namePrefix . $name, $this->applyGroupParams($route));
132
133 284
        return $this;
134
    }
135
136 284
    private function applyGroupParams(Route $route): Route
137
    {
138 284
        if ($this->core !== null) {
139 2
            $target = $route->getTarget();
140
141 2
            if ($target instanceof AbstractTarget) {
142 2
                $route = $route->withTarget($target->withCore($this->core));
143
            }
144
        }
145
146
        try {
147 284
            $uriHandler = $route->getUriHandler();
148 284
        } catch (\Throwable) {
149 284
            $uriHandler = $this->handler;
150
        }
151
152 284
        return $route->withUriHandler($uriHandler->withPrefix($this->prefix));
153
    }
154
}
155