Completed
Push — master ( d41cf1...36fce9 )
by Javi
23:31
created

RouteDispatcher::dispatch()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 30
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 16
nc 6
nop 2
1
<?php
2
3
namespace Philae\Middlewares;
4
5
use FastRoute\Dispatcher as FastRouteDispatcher;
6
use FastRoute\Dispatcher\GroupCountBased as GroupCountBasedDispatcher;
7
use FastRoute\RouteCollector;
8
use Interop\Http\ServerMiddleware\DelegateInterface;
9
use Middlewares\HttpErrorException;
10
use Middlewares\Utils\CallableResolver\CallableResolverInterface;
11
use Philae\DefaultServiceProvider;
12
use Psr\Http\Message\ResponseInterface;
13
use Psr\Http\Message\ServerRequestInterface;
14
15
class RouteDispatcher extends AbstractMiddleware
16
{
17
    /**
18
     * @var string Middleware attribute name
19
     */
20
    protected $attribute = 'request-handler';
21
22
    /**
23
     * @var FastRouteDispatcher FastRoute dispatcher
24
     */
25
    protected $dispatcherClass;
26
27
    /**
28
     * @param string $dispatcherClass
29
     */
30
    public function __construct(string $dispatcherClass = GroupCountBasedDispatcher::class)
31
    {
32
        $this->dispatcherClass = $dispatcherClass;
0 ignored issues
show
Documentation Bug introduced by
It seems like $dispatcherClass of type string is incompatible with the declared type object<FastRoute\Dispatcher> of property $dispatcherClass.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
33
    }
34
35
    /**
36
     * Set the FastRoute dispatcher class name.
37
     *
38
     * @param string $className
39
     *
40
     * @return $this
41
     */
42
    public function dispatcherClass(string $className)
43
    {
44
        $this->dispatcherClass = $className;
0 ignored issues
show
Documentation Bug introduced by
It seems like $className of type string is incompatible with the declared type object<FastRoute\Dispatcher> of property $dispatcherClass.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
45
46
        return $this;
47
    }
48
49
    /**
50
     * Process a server request and return a response.
51
     *
52
     * @param ServerRequestInterface $request
53
     * @param DelegateInterface $delegate
54
     *
55
     * @return ResponseInterface
56
     */
57
    public function process(ServerRequestInterface $request, DelegateInterface $delegate)
58
    {
59
        $dispatcherClass = $this->dispatcherClass;
60
61
        /** @var RouteCollector $router */
62
        $router     = $this->getContainer()->get(DefaultServiceProvider::SERVICE_ROUTE_COLLECTOR);
63
        $dispatcher = new $dispatcherClass($router->getData());
64
        $handler    = $this->dispatch($request, $dispatcher);
65
        $request    = $request->withAttribute($this->attribute, $handler);
66
67
        return $delegate->process($request);
68
    }
69
70
    /**
71
     * @param ServerRequestInterface $request
72
     * @param FastRouteDispatcher $dispatcher
73
     * @return \Closure The request handler callable
74
     * @throws HttpErrorException
75
     */
76
    public function dispatch(ServerRequestInterface $request, FastRouteDispatcher $dispatcher = null)
77
    {
78
        if (!$dispatcher) {
79
            /** @var RouteCollector $router */
80
            $router     = $this->getContainer()->get(DefaultServiceProvider::SERVICE_ROUTE_COLLECTOR);
81
            $dispatcher = new GroupCountBasedDispatcher($router->getData());
82
        }
83
84
        $match = $dispatcher->dispatch(
85
            strtoupper($request->getMethod()),
86
            $request->getUri()->getPath()
87
        );
88
89
        if ($match[0] === FastRouteDispatcher::NOT_FOUND) {
90
            throw HttpErrorException::create(404, ['request' => $request]);
91
        }
92
93
        if ($match[0] === FastRouteDispatcher::METHOD_NOT_ALLOWED) {
94
            throw HttpErrorException::create(405, ['request' => $request, 'allowed' => (array)$match[1]]);
95
        }
96
97
        /** @var CallableResolverInterface $resolver */
98
        $resolver = $this->getContainer()->get(DefaultServiceProvider::SERVICE_CALLABLE_RESOLVER);
99
        $callable = $resolver->resolve($match[1]);
100
        $params   = (array)$match[2];
101
102
        return function (...$args) use ($callable, $params) {
103
            return call_user_func($callable, ...array_values($params), ...$args);
104
        };
105
    }
106
}
107