FindRoutes   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 12
eloc 24
c 2
b 0
f 0
dl 0
loc 97
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A factorizeMiddleware() 0 8 2
A matchRoute() 0 7 2
A extractClosure() 0 3 1
A __construct() 0 6 1
A find() 0 15 3
A removeIntegerKeyParam() 0 10 3
1
<?php
2
3
namespace Tleckie\Router;
4
5
use Tleckie\Router\Exception\RouteNotFoundException;
6
use Closure;
7
use function array_pop;
8
use function is_numeric;
9
use function preg_match_all;
10
11
/**
12
 * Class FindRoutes
13
 *
14
 * @package Tleckie\Router
15
 * @author  Teodoro Leckie Westberg <[email protected]>
16
 */
17
class FindRoutes
18
{
19
    /** @var MiddlewareFactory */
20
    private MiddlewareFactory $middlewareFactory;
21
22
    /** @var array */
23
    private array $routes;
24
25
    /**
26
     * FindRoutes constructor.
27
     *
28
     * @param MiddlewareFactory $middlewareFactory
29
     * @param array             $routes
30
     */
31
    public function __construct(
32
        MiddlewareFactory $middlewareFactory,
33
        array $routes
34
    ) {
35
        $this->middlewareFactory = $middlewareFactory;
36
        $this->routes = $routes;
37
    }
38
39
    /**
40
     * @param string $method
41
     * @param string $path
42
     * @return Item
43
     * @throws RouteNotFoundException
44
     */
45
    public function find(string $method, string $path): Item
46
    {
47
        foreach ($this->routes[$method] ?? [] as $pattern => $closures) {
48
            if (null !== $params = $this->matchRoute($pattern, $path)) {
49
                $params = $this->removeIntegerKeyParam($params);
50
51
                $closure = $this->extractClosure($closures);
52
53
                $middlewares = $this->factorizeMiddleware($closures, $params);
54
55
                return new Item($closure, $params, $middlewares);
56
            }
57
        }
58
59
        throw new RouteNotFoundException('Routes not match');
60
    }
61
62
    /**
63
     * @param string $pattern
64
     * @param string $path
65
     * @return array|bool
66
     */
67
    private function matchRoute(string $pattern, string $path): ?array
68
    {
69
        if (preg_match_all("#^{$pattern}$#", $path, $matches, PREG_SET_ORDER)) {
70
            return $matches[0] ?? [];
71
        }
72
73
        return null;
74
    }
75
76
    /**
77
     * @param array $params
78
     * @return array
79
     */
80
    private function removeIntegerKeyParam(array $params): array
81
    {
82
        $returnParams = [];
83
        foreach ($params as $paramKey => $paramValue) {
84
            if (!is_numeric($paramKey)) {
85
                $returnParams[$paramKey] = $paramValue;
86
            }
87
        }
88
89
        return $returnParams;
90
    }
91
92
    /**
93
     * @param array $closures
94
     * @return Closure|callable
95
     */
96
    private function extractClosure(array &$closures): Closure|callable
97
    {
98
        return array_pop($closures);
99
    }
100
101
    /**
102
     * @param array $closures
103
     * @param array $params
104
     * @return array
105
     */
106
    private function factorizeMiddleware(array $closures, array $params): array
107
    {
108
        $middleware = [];
109
        foreach ($closures as $closure) {
110
            $middleware[] = $this->middlewareFactory->create($closure, $params);
111
        }
112
113
        return $middleware;
114
    }
115
}
116