Completed
Push — master ( 90174b...a197f9 )
by Changwan
03:50
created

CompiledRoutes   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 84
ccs 39
cts 39
cp 1
rs 10
c 0
b 0
f 0
wmc 12
lcom 1
cbo 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B compile() 0 36 6
A __construct() 0 5 1
B dispatch() 0 23 5
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 24
    public static function compile(Closure $handler, Configuration $config)
23
    {
24 24
        $routeMap = [];
25 24
        $router = new Router;
26 24
        $router->middleware($config->getMiddleware(), $handler);
27
28
        /** @var \FastRoute\DataGenerator\GroupCountBased[] $generators */
29 24
        $generators = [];
30
        /**
31
         * @var array|string[] $methods
32
         * @var string $path
33
         * @var \Wandu\Router\Route $route
34
         */
35 24
        foreach ($router as list($methods, $path, $route)) {
36 24
            $pathPattern = new Pattern($path);
37
38 24
            $handleId = uniqid('HANDLER');
39 24
            $routeMap[$handleId] = $route;
40
41 24
            foreach ($pathPattern->parse() as $parsedPath) {
42 24
                foreach ($methods as $method) {
43 24
                    foreach ($route->getDomains() as $domain) {
0 ignored issues
show
Bug introduced by
The expression $route->getDomains() of type string is not traversable.
Loading history...
44 24
                        if (!isset($generators[$domain])) {
45 24
                            $generators[$domain] = new GCBGenerator();
46
                        }
47 24
                        $generators[$domain]->addRoute($method, $parsedPath, $handleId);
48
                    }
49
                }
50
            }
51
        }
52
53 24
        $compiledRoutes = array_map(function (GCBGenerator $generator) {
54 24
            return $generator->getData();
55 24
        }, $generators);
56 24
        return new static($compiledRoutes, $routeMap);
57
    }
58
59
    /** @var \Wandu\Router\Route[] */
60
    protected $routeMap = [];
61
62
    /** @var array */
63
    protected $compiledRoutes = [];
64
65
    /**
66
     * @param array $compiledRoutes
67
     * @param array $routeMap
68
     */
69 24
    public function __construct(array $compiledRoutes, array $routeMap)
70
    {
71 24
        $this->routeMap = $routeMap;
72 24
        $this->compiledRoutes = $compiledRoutes;
73 24
    }
74
    
75 24
    public function dispatch(ServerRequestInterface $request, LoaderInterface $loader = null, ResponsifierInterface $responsifier = null)
76
    {
77 24
        $host = $request->getHeaderLine('host');
78 24
        $compiledRoutes = array_key_exists($host, $this->compiledRoutes)
79 1
            ? $this->compiledRoutes[$host]
80 24
            : $this->compiledRoutes['@'];
81
        
82 24
        $routeInfo = (new GCBDispatcher($compiledRoutes))
83 24
            ->dispatch($request->getMethod(), '/' . trim($request->getUri()->getPath(), '/'));
84
        
85 24
        switch ($routeInfo[0]) {
86 24
            case FastDispatcher::NOT_FOUND:
87 1
                throw new RouteNotFoundException();
88 24
            case FastDispatcher::METHOD_NOT_ALLOWED:
89 9
                throw new MethodNotAllowedException();
90
        }
91 23
        $route = $this->routeMap[$routeInfo[1]];
92 23
        foreach ($routeInfo[2] as $key => $value) {
93 5
            $request = $request->withAttribute($key, $value);
94
        }
95
        
96 23
        return $route->execute($request, $loader, $responsifier);
97
    }
98
}
99