Completed
Push — master ( 27d2f2...3153a3 )
by Changwan
04:10
created

CompiledRoutes::dispatch()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.0106

Importance

Changes 0
Metric Value
cc 6
eloc 15
nc 7
nop 3
dl 0
loc 23
ccs 14
cts 15
cp 0.9333
crap 6.0106
rs 8.5906
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Router;
3
4
use Closure;
5
use FastRoute\DataGenerator\GroupCountBased as GCBGenerator;
6
use FastRoute\Dispatcher as FastDispatcher;
7
use FastRoute\Dispatcher\GroupCountBased as GCBDispatcher;
8
use Psr\Http\Message\ServerRequestInterface;
9
use Wandu\Router\Contracts\LoaderInterface;
10
use Wandu\Router\Contracts\ResponsifierInterface;
11
use Wandu\Router\Exception\MethodNotAllowedException;
12
use Wandu\Router\Exception\RouteNotFoundException;
13
use Wandu\Router\Path\Pattern;
14
15
class CompiledRoutes
16
{
17
    /**
18
     * @param \Closure $handler
19
     * @param \Wandu\Router\Configuration $config
20
     * @return \Wandu\Router\CompiledRoutes
21
     */
22 25
    public static function compile(Closure $handler, Configuration $config)
23
    {
24 25
        $resultRoutes = [];
25 25
        $resultNamedPath = [];
26
27 25
        $router = new Router;
28 25
        $router->middleware($config->getMiddleware(), $handler);
29
30 25
        $generator = new GCBGenerator();
31
        /**
32
         * @var array|string[] $methods
33
         * @var string $path
34
         * @var \Wandu\Router\Route $route
35
         */
36 25
        foreach ($router as list($methods, $path, $route)) {
37 25
            $pathPattern = new Pattern($path);
38 25
            if ($routeName = $route->getName()) {
39 1
                $resultNamedPath[$routeName] = $pathPattern;
40
            }
41 25
            foreach ($pathPattern->parse() as $parsedPath) {
42 25
                foreach ($methods as $method) {
43 25
                    $handleId = uniqid('HANDLER');
44 25
                    $generator->addRoute($method, $parsedPath, $handleId);
45 25
                    $resultRoutes[$handleId] = $route;
46
                }
47
            }
48
        }
49 25
        return new static($resultRoutes, $resultNamedPath, $generator->getData());
50
    }
51
52
    /** @var \Wandu\Router\Route[] */
53
    protected $routes = [];
54
55
    /** @var \Wandu\Router\Route[] */
56
    protected $namedPattern;
57
58
    /** @var array */
59
    protected $compiledRoutes = [];
60
61
    /**
62
     * @param array $routes
63
     * @param array $namedPattern
64
     * @param array $compiledRoutes
65
     */
66 25
    public function __construct(array $routes, array $namedPattern, array $compiledRoutes)
67
    {
68 25
        $this->routes = $routes;
69 25
        $this->namedPattern = $namedPattern;
70 25
        $this->compiledRoutes = $compiledRoutes;
71 25
    }
72
    
73 1
    public function getPattern($name): Pattern
74
    {
75 1
        if (!isset($this->namedPattern[$name])) {
76 1
            throw new RouteNotFoundException("Route \"{$name}\" not found.");
77
        }
78 1
        return $this->namedPattern[$name];
79
80
    }
81 24
    public function dispatch(ServerRequestInterface $request, LoaderInterface $loader = null, ResponsifierInterface $responsifier = null)
82
    {
83 24
        $routeInfo = (new GCBDispatcher($this->compiledRoutes))
84 24
            ->dispatch($request->getMethod(), $request->getUri()->getPath());
85
        
86 24
        switch ($routeInfo[0]) {
87 24
            case FastDispatcher::NOT_FOUND:
88
                throw new RouteNotFoundException();
89 24
            case FastDispatcher::METHOD_NOT_ALLOWED:
90 8
                throw new MethodNotAllowedException();
91
        }
92 23
        $route = $this->routes[$routeInfo[1]];
93 23
        if (count($domains = $route->getDomains())) {
94 1
            if (!in_array($request->getHeaderLine('host'), $domains)) {
95 1
                throw new RouteNotFoundException();
96
            }
97
        }
98 23
        foreach ($routeInfo[2] as $key => $value) {
99 5
            $request = $request->withAttribute($key, $value);
100
        }
101
        
102 23
        return $route->execute($request, $loader, $responsifier);
103
    }
104
}
105