Completed
Push — master ( 28e5e2...3bec47 )
by Mathieu
01:38
created

Route::computePath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 9
ccs 5
cts 6
cp 0.8333
crap 2.0185
rs 9.6666
c 0
b 0
f 0
1
<?php
2
namespace Suricate;
3
4
class Route
5
{
6
    private $name;
7
    private $method;
8
    private $path;
9
    private $computedPath;
10
11
    private $parametersDefinitions;
12
    public $parametersValues;
13
14
    public $isMatched;
15
    public $target;
16
    public $middlewares = array();
17
    
18 1
    public function __construct($name, $method, $path, $request, $routeTarget, $parametersDefinitions = array(), $middleware = null)
19
    {
20 1
        $this->isMatched                = false;
21 1
        $this->name                     = $name;
22 1
        $this->method                   = $method;
23 1
        $this->path                     = $path;
24 1
        $this->target                   = $routeTarget;
25 1
        $this->parametersDefinitions    = $parametersDefinitions;
26 1
        $this->parametersValues         = array();
27 1
        $this->middlewares              = (array)$middleware;
28
29 1
        $this->setParameters();
30 1
        $this->computePath();
31 1
        $this->match($request);
32 1
    }
33
34
    /**
35
     * Get route path
36
     * @return string
37
     */
38 1
    public function getPath()
39
    {
40 1
        return $this->path;
41
    }
42
43 1
    private function match($request)
44
    {
45 1
        $requestUri = $request->getRequestUri();
46
47 1
        if (($pos = strpos($requestUri, '?')) !== false) {
48
            $requestUri = substr($requestUri, 0, $pos);
49
        }
50
51 1
        if ($this->method == 'any' || strtolower($this->method) == strtolower($request->getMethod())) {
52
            // requestUri is matching pattern, set as matched route
53 1
            if (preg_match('#^' . $this->computedPath . '$#', $requestUri, $matching)) {
54
                foreach (array_keys($this->parametersDefinitions) as $currentParameter) {
55
                    $this->parametersValues[$currentParameter] = isset($matching[$currentParameter]) ? $matching[$currentParameter] : null;
56
                }
57
58
                $this->isMatched        = true;
59
            }
60 1
        }
61 1
    }
62
63
    public function dispatch($response, $middlewares = array())
64
    {
65
        $result     = false;
66
        $callable   = $this->getCallable($response);
67
        if (is_callable($callable)) {
68
            $this->middlewares = array_merge($middlewares, $this->middlewares);
69
            
70
            // We found a valid method for this controller
71
            // Find parameters order
72
            $methodArguments = $this->getCallableArguments();
73
74
            // Calling $controller->method with arguments in right order
75
            
76
            // Middleware stack processing
77
            foreach ($this->middlewares as $middleware) {
78
                if (is_object($middleware)) {
79
                    $middleware->call($response);
80
                } else {
81
                    with(new $middleware)->call($response);
82
                }
83
            }
84
            
85
            $result = call_user_func_array($callable, $methodArguments);
86
        }
87
88
        return $result;
89
    }
90
91
    private function getCallable($response)
92
    {
93
        if (count($this->target) > 1) {
94
            $callable = array(
95
                new $this->target[0]($response, $this),
96
                $this->target[1]
97
            );
98
        } else {
99
            $callable = $this->target;
100
        }
101
102
        return $callable;
103
    }
104
105
    private function getCallableArguments()
106
    {
107
        if (count($this->target) > 1) {
108
            $reflection = new \ReflectionMethod($this->target[0], $this->target[1]);
109
        } else {
110
            $reflection = new \ReflectionFunction($this->target);
111
        }
112
        
113
        $methodParameters = $reflection->getParameters();
114
        $methodArguments = array();
115
116
        foreach ($methodParameters as $index => $parameter) {
117
            if (isset($this->parametersValues[$parameter->name])) {
118
                $methodArguments[$index] = urldecode($this->parametersValues[$parameter->name]);
119
            } else {
120
                // No value matching this parameter
121
                $methodArguments[$index] = null;
122
            }
123
        }
124
125
        return $methodArguments;
126
    }
127
128 1
    protected function setParameters()
129
    {
130
        // Get all route parameters
131 1
        preg_match_all('|:([\w]+)|', $this->path, $routeParameters);
132 1
        $routeParametersNames = $routeParameters[1];
133
134 1
        foreach ($routeParametersNames as $parameter) {
135
            // Patterns parameters are not set, considering implicit declaration
136
            if (!isset($this->parametersDefinitions[$parameter])) {
137
                $this->parametersDefinitions[$parameter] = '.*';
138
            }
139 1
        }
140 1
    }
141
142
    /**
143
     * Build PCRE pattern path, according to route parameters
144
     * @return null
145
     */
146 1
    protected function computePath()
147
    {
148 1
        $this->computedPath = $this->path;
149
150
        // Assigning parameters
151 1
        foreach ($this->parametersDefinitions as $parameterName => $parameterDefinition) {
152
            $this->computedPath = str_replace(':' . $parameterName, '(?<' . $parameterName . '>' . $parameterDefinition . ')', $this->computedPath);
153 1
        }
154 1
    }
155
}
156