Passed
Branch master (7c3f6c)
by Javi
02:38
created

RouteCollector::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 4
nc 4
nop 2
1
<?php
2
3
namespace itsjavi\Flatdown\Route;
4
5
use FastRoute\DataGenerator;
6
use FastRoute\DataGenerator\GroupCountBased as GroupCountBasedDataGenerator;
7
use FastRoute\Dispatcher as FastRouteDispatcher;
8
use FastRoute\Dispatcher\GroupCountBased as GroupCountBasedDispatcher;
9
use FastRoute\RouteParser;
10
use FastRoute\RouteParser\Std as StdRouteParser;
11
use Middlewares\HttpErrorException;
12
use Middlewares\Utils\CallableResolver\CallableResolverInterface;
13
use Middlewares\Utils\CallableResolver\ReflectionResolver;
14
use Psr\Http\Message\ServerRequestInterface;
15
16
class RouteCollector extends \FastRoute\RouteCollector
17
{
18
    /**
19
     * @var CallableResolverInterface
20
     */
21
    protected $callableResolver;
22
23
    /**
24
     * @param \FastRoute\RouteParser $parser
25
     * @param \FastRoute\DataGenerator $generator
26
     */
27
    public function __construct(RouteParser $parser = null, DataGenerator $generator = null)
28
    {
29
        $parser    = $parser ?: new StdRouteParser;
30
        $generator = $generator ?: new GroupCountBasedDataGenerator;
31
32
        parent::__construct($parser, $generator);
33
    }
34
35
    /**
36
     * @return CallableResolverInterface
37
     */
38
    protected function getCallableResolver()
39
    {
40
        if (!$this->callableResolver) {
41
            $this->callableResolver = new ReflectionResolver();
42
        }
43
44
        return $this->callableResolver;
45
    }
46
47
    /**
48
     * @param CallableResolverInterface $callableResolver
49
     * @return RouteCollector
50
     */
51
    public function setCallableResolver(CallableResolverInterface $callableResolver)
52
    {
53
        $this->callableResolver = $callableResolver;
54
55
        return $this;
56
    }
57
58
    /**
59
     * @param ServerRequestInterface $request
60
     * @param FastRouteDispatcher|null $dispatcher
61
     * @return \Closure The request handler callable
62
     * @throws HttpErrorException
63
     */
64
    public function dispatch(ServerRequestInterface $request, FastRouteDispatcher $dispatcher = null)
65
    {
66
        if (!$dispatcher) {
67
            $dispatcher = new GroupCountBasedDispatcher($this->getData());
68
        }
69
70
        $match = $dispatcher->dispatch(
71
            $request->getMethod(),
72
            $request->getUri()->getPath()
73
        );
74
75
        if ($match[0] === FastRouteDispatcher::NOT_FOUND) {
76
            throw HttpErrorException::create(404, ['request' => $request]);
77
        }
78
79
        if ($match[0] === FastRouteDispatcher::METHOD_NOT_ALLOWED) {
80
            throw HttpErrorException::create(405, ['request' => $request, 'allowed' => (array)$match[1]]);
81
        }
82
83
        $callable = $this->getCallable($match[1]);
84
        $params   = (array)$match[2];
85
86
        return function (ServerRequestInterface $request, ...$args) use ($callable, $params) {
87
            return call_user_func($callable, $request, $params, ...$args);
88
        };
89
    }
90
91
    /**
92
     * @param callable|mixed $callable
93
     * @return array|callable
94
     */
95
    protected function getCallable($callable)
96
    {
97
        // Add invokable class support
98
        if (is_string($callable)
99
            && (strpos($callable, '::') === false)
100
            && class_exists($callable)
101
            && function_exists($callable . '::__invoke')
102
        ) {
103
            return [$callable, '__invoke'];
104
        }
105
106
        return $this->getCallableResolver()->resolve($callable, []);
107
    }
108
}
109