Passed
Pull Request — master (#1168)
by Aleksei
12:55
created

Route::requestHandler()   B

Complexity

Conditions 8
Paths 24

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 8.048

Importance

Changes 0
Metric Value
eloc 21
c 0
b 0
f 0
dl 0
loc 34
ccs 20
cts 22
cp 0.9091
rs 8.4444
cc 8
nc 24
nop 0
crap 8.048
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Router;
6
7
use Psr\Container\ContainerExceptionInterface;
8
use Psr\Container\ContainerInterface;
9
use Psr\Http\Message\ResponseFactoryInterface;
10
use Psr\Http\Message\ResponseInterface;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Psr\Http\Server\RequestHandlerInterface;
13
use Spiral\Http\CallableHandler;
14
use Spiral\Router\Exception\RouteException;
15
use Spiral\Router\Exception\TargetException;
16
use Spiral\Router\Traits\LazyPipelineTrait;
0 ignored issues
show
Bug introduced by
The type Spiral\Router\Traits\LazyPipelineTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Spiral\Router\Traits\PipelineTrait;
18
19
/**
20
 * Default route provides ability to route request to a given callable handler.
21
 *
22
 * Examples:
23
 *
24
 * new Route("/login", function(){
25
 *   return "hello";
26
 * });
27
 * new Route("/login", new Handler());
28
 * new Route("/login", \App\Handlers\Handler::class);
29
 *
30
 * new Route("/login", new Action(\App\Controllers|HomeController::class, "login");
31
 * new Route("/<controller>/<action>/<id>", new Namespaced("\App\Controllers");
32
 * new Route("/signup/<action>", new Controller(\App\Controllers\SignupController::class);
33
 * new Route("://<domain>/info", new Action(\App\Controllers|ProfileController::class, "info");
34
 * new Route("/<controller>/<action>/<id>", new Group(["profile" =>
35
 * \App\Controllers|ProfileController::class]);
36
 */
37
final class Route extends AbstractRoute implements ContainerizedInterface
0 ignored issues
show
Bug introduced by
The type Spiral\Router\AbstractRoute was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
38
{
39
    use PipelineTrait;
40
41
    public const ROUTE_ATTRIBUTE = 'route';
42
43
    /** @var string|callable|RequestHandlerInterface|TargetInterface */
44
    private mixed $target;
45
    private ?RequestHandlerInterface $requestHandler = null;
46
47
    /**
48
     * @param string $pattern Uri pattern.
49
     * @param string|callable|RequestHandlerInterface|TargetInterface $target Callable route target.
50
     * @param array $defaults Default value set.
51
     */
52 478
    public function __construct(
53
        string $pattern,
54
        string|callable|RequestHandlerInterface|TargetInterface $target,
55
        array $defaults = []
56
    ) {
57 478
        parent::__construct(
58 478
            $pattern,
59 478
            $target instanceof TargetInterface
60 455
                ? \array_merge($target->getDefaults(), $defaults)
61 478
                : $defaults
62 478
        );
63
64 478
        $this->target = $target;
65
    }
66
67
    /**
68
     * @mutation-free
69
     */
70 469
    public function withUriHandler(UriHandler $uriHandler): static
71
    {
72 469
        if ($this->target instanceof TargetInterface) {
73 450
            $uriHandler = $uriHandler->withConstrains(
74 450
                $this->target->getConstrains(),
75 450
                $this->defaults,
76 450
            );
77
        }
78
79 469
        return parent::withUriHandler($uriHandler);
80
    }
81
82
    /**
83
     * Associated route with given container.
84
     */
85 438
    public function withContainer(ContainerInterface $container): ContainerizedInterface
86
    {
87 438
        $route = clone $this;
88 438
        $route->container = $container;
89
90 438
        if ($route->target instanceof TargetInterface) {
91 425
            $route->target = clone $route->target;
92
        }
93
94 438
        $route->pipeline = $route->makeLazyPipeline();
95
96 436
        return $route;
97
    }
98
99 2
    public function withTarget(mixed $target): static
100
    {
101 2
        $route = clone $this;
102 2
        $route->target = $target;
103
104 2
        return $route;
105
    }
106
107 2
    public function getTarget(): mixed
108
    {
109 2
        return $this->target;
110
    }
111
112
    /**
113
     * @throws RouteException
114
     */
115 57
    public function handle(ServerRequestInterface $request): ResponseInterface
116
    {
117 57
        if (empty($this->requestHandler)) {
118 57
            $this->requestHandler = $this->requestHandler();
119
        }
120
121 54
        \assert($this->pipeline !== null);
122 54
        return $this->pipeline->process(
123 54
            $request->withAttribute(self::ROUTE_ATTRIBUTE, $this),
124 54
            $this->requestHandler
0 ignored issues
show
Bug introduced by
It seems like $this->requestHandler can also be of type null; however, parameter $handler of Spiral\Http\Pipeline::process() does only seem to accept Psr\Http\Server\RequestHandlerInterface, 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

124
            /** @scrutinizer ignore-type */ $this->requestHandler
Loading history...
Bug introduced by
It seems like $this->requestHandler can also be of type null; however, parameter $handler of Spiral\Http\LazyPipeline::process() does only seem to accept Psr\Http\Server\RequestHandlerInterface, 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

124
            /** @scrutinizer ignore-type */ $this->requestHandler
Loading history...
125 54
        );
126
    }
127
128
    /**
129
     * @throws RouteException
130
     */
131 57
    protected function requestHandler(): RequestHandlerInterface
132
    {
133 57
        $this->hasContainer() or throw new RouteException(
134 57
            'Unable to configure route pipeline without associated container.',
135 57
        );
136
137 55
        if ($this->target instanceof TargetInterface) {
138
            try {
139 48
                \assert($this->matches !== null);
140 48
                return $this->target->getHandler($this->container, $this->matches);
141
            } catch (TargetException $e) {
142
                throw new RouteException('Invalid target resolution', $e->getCode(), $e);
143
            }
144
        }
145
146 7
        if ($this->target instanceof RequestHandlerInterface) {
147 1
            return $this->target;
148
        }
149
150
        try {
151 6
            $target = \is_string($this->target)
152 4
                ? $this->container->get($this->target)
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

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

152
                ? $this->container->/** @scrutinizer ignore-call */ get($this->target)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
153 2
                : $this->target;
154
155 5
            if ($target instanceof RequestHandlerInterface) {
156 1
                return $target;
157
            }
158
159 4
            return new CallableHandler(
160 4
                $target,
161 4
                $this->container->get(ResponseFactoryInterface::class)
162 4
            );
163 1
        } catch (ContainerExceptionInterface $e) {
164 1
            throw new RouteException($e->getMessage(), $e->getCode(), $e);
165
        }
166
    }
167
}
168