Completed
Branch master (740422)
by Mathieu
02:04
created

Route::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1.0122

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 12
nc 1
nop 7
dl 0
loc 15
ccs 10
cts 13
cp 0.7692
crap 1.0122
rs 9.4285
c 2
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
        $this->setParameters();
30
        $this->computePath();
31
        $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
        $requestUri = $request->getRequestUri();
46
47
        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
            if (preg_match('#^' . $this->computedPath . '$#', $requestUri, $matching)) {
54
55
                foreach (array_keys($this->parametersDefinitions) as $currentParameter) {
56
                    $this->parametersValues[$currentParameter] = isset($matching[$currentParameter]) ? $matching[$currentParameter] : null;
57
                }
58
59
                $this->isMatched        = true;
60
            }
61
        }
62 1
    }
63
64
    public function dispatch($response, $middlewares =array())
65
    {
66
        $result     = false;
67
        $callable   = $this->getCallable($response);
68
        if (is_callable($callable)) {
69
            $this->middlewares = array_merge($middlewares, $this->middlewares);
70
            
71
            // We found a valid method for this controller
72
            // Find parameters order
73
            $methodArguments = $this->getCallableArguments();
74
75
            // Calling $controller->method with arguments in right order
76
            
77
            // Middleware stack processing
78
            foreach ($this->middlewares as $middleware) {
79
                if (is_object($middleware)) {
80
                    $middleware->call($response);
81
                } else {
82
                    with(new $middleware)->call($response);
83
                }
84
            }
85
            
86
            $result = call_user_func_array($callable, $methodArguments);
87
88
            
89
        }
90
91
        return $result;
92
    }
93
94
    private function getCallable($response)
95
    {
96
        if (count($this->target) > 1) {
97
            $callable = array(
98
                new $this->target[0]($response, $this),
99
                $this->target[1]
100
            );
101
        } else {
102
            $callable = $this->target;
103
        }
104
105
        return $callable;
106
    }
107
108
    private function getCallableArguments()
109
    {
110
        if (count($this->target) > 1) {
111
            $reflection = new \ReflectionMethod($this->target[0], $this->target[1]);
112
        } else {
113
            $reflection = new \ReflectionFunction($this->target);
114
        }
115
        
116
        $methodParameters = $reflection->getParameters();
117
        $methodArguments = array();
118
119
        foreach ($methodParameters as $index => $parameter) {
120
            if (isset($this->parametersValues[$parameter->name])) {
121
                $methodArguments[$index] = urldecode($this->parametersValues[$parameter->name]);
122
            } else {
123
                // No value matching this parameter
124
                $methodArguments[$index] = null;
125
            }
126
        }
127
128
        return $methodArguments;
129
    }
130
131 1
    protected function setParameters()
132
    {
133
        // Get all route parameters
134
        preg_match_all('|:([\w]+)|', $this->path, $routeParameters);
135 1
        $routeParametersNames = $routeParameters[1];
136
137
        foreach ($routeParametersNames as $parameter) {
138
            // Patterns parameters are not set, considering implicit declaration
139
            if (!isset($this->parametersDefinitions[$parameter])) {
140
                $this->parametersDefinitions[$parameter] = '.*';
141
            }
142 1
        }
143 1
    }
144
145
    /**
146
     * Build PCRE pattern path, according to route parameters
147
     * @return null
148
     */
149 1
    protected function computePath()
150
    {
151 1
        $this->computedPath = $this->path;
152
153
        // Assigning parameters
154 1
        foreach ($this->parametersDefinitions as $parameterName => $parameterDefinition) {
155
            $this->computedPath = str_replace(':' . $parameterName, '(?<' . $parameterName . '>' . $parameterDefinition . ')', $this->computedPath);
156 1
        }
157 1
    }
158
}
159