Dispatch   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 203
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 65
c 1
b 0
f 0
dl 0
loc 203
rs 10
wmc 25

9 Methods

Rating   Name   Duplication   Size   Complexity  
A execute() 0 29 5
A data() 0 3 1
A formSpoofing() 0 27 6
A __construct() 0 6 2
A __debugInfo() 0 3 1
A dispatch() 0 16 5
A error() 0 3 1
A group() 0 4 2
A namespace() 0 4 2
1
<?php
2
3
namespace Stonks\Router;
4
5
/**
6
 * Class Dispatch
7
 *
8
 * @package Stonks\Router
9
 */
10
class Dispatch
11
{
12
13
	use RouterTrait;
14
15
	/**
16
	 * @var array|null
17
	 */
18
	private $route;
19
20
	/**
21
	 * @var string
22
	 */
23
	private $projectUrl;
24
25
	/**
26
	 * @var string
27
	 */
28
	private $separator;
29
30
	/**
31
	 * @var string|null
32
	 */
33
	private $namespace;
34
35
	/**
36
	 * @var string|null
37
	 */
38
	private $group;
39
40
	/**
41
	 * @var array|null
42
	 */
43
	private $data;
44
45
	/**
46
	 * @var int
47
	 */
48
	private $error;
49
50
	/**
51
	 * @const int
52
	 */
53
	public const BAD_REQUEST = 400;
54
55
	/**
56
	 * @const int
57
	 */
58
	public const NOT_FOUND = 404;
59
60
	/**
61
	 * @const int
62
	 */
63
	public const METHOD_NOT_ALLOWED = 405;
64
65
	/**
66
	 * @const int
67
	 */
68
	public const NOT_IMPLEMENTED = 501;
69
70
	/**
71
	 * Dispatch constructor.
72
	 *
73
	 * @param string $projectUrl
74
	 * @param string $separator
75
	 */
76
	public function __construct(string $projectUrl, string $separator = ':')
77
	{
78
		$this->projectUrl = (substr($projectUrl, -1) === '/' ? substr($projectUrl, 0, '-1') : $projectUrl);
79
		$this->separator = ($separator ?? ':');
80
		$this->httpMethod = $_SERVER['REQUEST_METHOD'];
81
		$this->patch = (filter_input(INPUT_GET, 'route', FILTER_DEFAULT) ?? '/');
82
	}
83
84
	/**
85
	 * @return array|null
86
	 */
87
	public function __debugInfo(): ?array
88
	{
89
		return $this->routes;
90
	}
91
92
	/**
93
	 * @param string|null $namespace
94
	 * @return $this
95
	 */
96
	public function namespace(?string $namespace): Dispatch
97
	{
98
		$this->namespace = ($namespace ? ucwords($namespace) : null);
99
		return $this;
100
	}
101
102
	/**
103
	 * @param string|null $group
104
	 * @return $this
105
	 */
106
	public function group(?string $group): Dispatch
107
	{
108
		$this->group = ($group ? str_replace('/', '', $group) : null);
109
		return $this;
110
	}
111
112
	/**
113
	 * @return array|null
114
	 */
115
	public function data(): ?array
116
	{
117
		return $this->data;
118
	}
119
120
	/**
121
	 * @return int|null
122
	 */
123
	public function error(): ?int
124
	{
125
		return $this->error;
126
	}
127
128
	/**
129
	 * @return bool
130
	 */
131
	public function dispatch(): bool
132
	{
133
		if (empty($this->routes) || empty($this->routes[$this->httpMethod])) {
134
			$this->error = self::NOT_IMPLEMENTED;
135
			return false;
136
		}
137
138
		$this->route = null;
139
140
		foreach ($this->routes[$this->httpMethod] as $key => $route) {
141
			if (preg_match("~^{$key}$~", $this->patch, $found)) {
142
				$this->route = $route;
143
			}
144
		}
145
146
		return $this->execute();
147
	}
148
149
	/**
150
	 * @return bool
151
	 */
152
	private function execute(): bool
153
	{
154
		if ($this->route) {
155
			if (is_callable($this->route['handler'])) {
156
				call_user_func($this->route['handler'], ($this->route['data'] ?? []));
157
				return true;
158
			}
159
160
			$controller = $this->route['handler'];
161
162
			if (class_exists($controller)) {
163
				$method = $this->route['action'];
164
				$newController = new $controller($this);
165
166
				if (method_exists($controller, $method)) {
167
					$newController->$method(($this->route['data'] ?? []));
168
					return true;
169
				}
170
171
				$this->error = self::METHOD_NOT_ALLOWED;
172
				return false;
173
			}
174
175
			$this->error = self::BAD_REQUEST;
176
			return false;
177
		}
178
179
		$this->error = self::NOT_FOUND;
180
		return false;
181
	}
182
183
	/**
184
	 * @return void
185
	 */
186
	private function formSpoofing(): void
187
	{
188
		$post = filter_input_array(INPUT_POST, FILTER_DEFAULT);
189
190
		if (!empty($post['_method']) && in_array($post['_method'], ['PUT', 'PATCH', 'DELETE'])) {
191
			$this->httpMethod = $post['_method'];
192
			$this->data = $post;
193
194
			unset($this->data['_method']);
195
			return;
196
		}
197
198
		if ($this->httpMethod === 'POST') {
199
			$this->data = $post;
200
201
			unset($this->data['_method']);
202
			return;
203
		}
204
205
		if (in_array($this->httpMethod, ['PUT', 'PATCH', 'DELETE']) && !empty($_SERVER['CONTENT_LENGTH'])) {
206
			parse_str(file_get_contents('php://input', false, null, 0, $_SERVER['CONTENT_LENGTH']), $this->data);
207
208
			unset($this->data['_method']);
209
			return;
210
		}
211
212
		$this->data = [];
213
	}
214
}
215