Passed
Push — master ( 242b35...9e2fe8 )
by Wanderson
02:32
created

Router::add()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Win\Services;
4
5
use Win\Common\Traits\InjectableTrait;
6
use Win\Common\Utils\Input;
7
use Win\HttpException;
8
9
/**
10
 * Rota de URL
11
 *
12
 * Define o [Controller, action] a ser executado baseado na URL
13
 * @see "config/routes.php"
14
 */
15
class Router
16
{
17
	use InjectableTrait;
18
	const HOME = ['index', 'index'];
19
	const SUFFIX = '/';
20
21
	/** @var string HTTPS/HTTP */
22
	public $protocol;
23
24
	/** @var string URL Base */
25
	public $baseUrl;
26
27
	/** @var string URL Relativa */
28
	public $relativeUrl;
29
30
	/** @var string URL Completa/Absoluta */
31
	public $url;
32
33
	/** @var string[] fragmentos da URL */
34
	public $segments;
35
	public $page;
36
	public $action;
37
38
	/** @var string[][] url => [Controller, action] */
39
	public $routes = [];
40
41
	public function __construct()
42
	{
43
		$this->protocol = Input::protocol();
44
		$this->baseUrl = $this->getBaseUrl();
45
		$this->relativeUrl = $this->getRelativeUrl();
46
		$this->segments = $this->getSegments();
47
		$this->url = $this->baseUrl . $this->relativeUrl;
48
	}
49
50
	/**
51
	 * Percorre todas as rotas e retorna o destino final
52
	 * @return array Destino
53
	 * @example return [Controller, action, ...$args]
54
	 */
55
	public function getDestination()
56
	{
57
		$url = $this->format($this->relativeUrl);
58
		$args = [];
59
60
		foreach ($this->routes as $request => $destination) {
61
			$pattern = '@^' . $this->format($request) . '$@';
62
			$match = preg_match($pattern, $url, $args);
63
			if ($match) {
64
				return [...$destination, ...array_splice($args, 1)];
65
			}
66
		}
67
68
		throw new HttpException('Route not found, check "config/routes.php"', 404);
69
	}
70
71
72
	/**
73
	 * Retorna no formato de URL
74
	 * @param string $url
75
	 * @return string
76
	 */
77
	public function format($url)
78
	{
79
		return rtrim($url, static::SUFFIX) . static::SUFFIX;
80
	}
81
82
	/**
83
	 * Redireciona para a URL escolhida
84
	 * @param string $url URL relativa ou absoluta
85
	 * @codeCoverageIgnore
86
	 */
87
	public function redirect($url = '')
88
	{
89
		if (false === strpos($url, '://')) {
90
			$url = $this->baseUrl . $url;
91
		}
92
		header('location:' . $url);
93
		die();
94
	}
95
96
	/**
97
	 * Volta para o método index da pagina atual
98
	 * @codeCoverageIgnore
99
	 */
100
	public function redirectToIndex()
101
	{
102
		$this->redirect($this->segments[0]);
103
	}
104
105
	/**
106
	 * Atualiza a mesma página
107
	 * @param string $url
108
	 * @codeCoverageIgnore
109
	 */
110
	public function refresh()
111
	{
112
		$this->redirect($this->url);
113
	}
114
115
	/**
116
	 * Retorna a URL base
117
	 * @return string
118
	 */
119
	private function getBaseUrl()
120
	{
121
		$host = Input::server('HTTP_HOST');
122
		if ($host) {
123
			$script = Input::server('SCRIPT_NAME');
124
			$baseUrl = preg_replace('@/+$@', '', dirname($script));
125
			return $this->protocol . '://' . $host . $baseUrl . '/';
126
		}
127
	}
128
129
	/**
130
	 * Define o final da URL
131
	 * @return string
132
	 */
133
	private function getRelativeUrl()
134
	{
135
		$host = Input::server('HTTP_HOST');
136
		if ($host) {
137
			$requestUri = explode('?', Input::server('REQUEST_URI'));
138
			$context = explode($host, $this->baseUrl);
139
			$uri = (explode(end($context), $requestUri[0], 2));
140
			return end($uri);
141
		}
142
	}
143
144
	/**
145
	 * Define os fragmentos da URL
146
	 * @return string[]
147
	 */
148
	private function getSegments()
149
	{
150
		return array_filter(explode('/', $this->relativeUrl)) + static::HOME;
151
	}
152
}
153