Total Complexity | 51 |
Total Lines | 273 |
Duplicated Lines | 0 % |
Changes | 2 | ||
Bugs | 0 | Features | 0 |
Complex classes like UriDetector often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use UriDetector, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
30 | class UriDetector |
||
31 | { |
||
32 | /** |
||
33 | * The URL components |
||
34 | * |
||
35 | * @var array |
||
36 | */ |
||
37 | protected $aUrl; |
||
38 | |||
39 | /** |
||
40 | * @param array $aServerParams The server environment variables |
||
41 | * |
||
42 | * @return void |
||
43 | */ |
||
44 | private function setScheme(array $aServerParams): void |
||
45 | { |
||
46 | if(isset($this->aUrl['scheme'])) |
||
47 | { |
||
48 | return; |
||
49 | } |
||
50 | if(isset($aServerParams['HTTP_SCHEME'])) |
||
51 | { |
||
52 | $this->aUrl['scheme'] = $aServerParams['HTTP_SCHEME']; |
||
53 | return; |
||
54 | } |
||
55 | if((isset($aServerParams['HTTPS']) && strtolower($aServerParams['HTTPS']) === 'on') || |
||
56 | (isset($aServerParams['HTTP_X_FORWARDED_SSL']) && $aServerParams['HTTP_X_FORWARDED_SSL'] === 'on') || |
||
57 | (isset($aServerParams['HTTP_X_FORWARDED_PROTO']) && $aServerParams['HTTP_X_FORWARDED_PROTO'] === 'https')) |
||
58 | { |
||
59 | $this->aUrl['scheme'] = 'https'; |
||
60 | return; |
||
61 | } |
||
62 | $this->aUrl['scheme'] = 'http'; |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Get the URL from the $aServerParams var |
||
67 | * |
||
68 | * @param array $aServerParams The server environment variables |
||
69 | * @param string $sKey The key in the $aServerParams array |
||
70 | * |
||
71 | * @return void |
||
72 | */ |
||
73 | private function setHostFromServer(array $aServerParams, string $sKey): void |
||
74 | { |
||
75 | if(isset($this->aUrl['host']) || empty($aServerParams[$sKey])) |
||
76 | { |
||
77 | return; |
||
78 | } |
||
79 | if(strpos($aServerParams[$sKey], ':') === false) |
||
80 | { |
||
81 | $this->aUrl['host'] = $aServerParams[$sKey]; |
||
82 | return; |
||
83 | } |
||
84 | list($this->aUrl['host'], $this->aUrl['port']) = explode(':', $aServerParams[$sKey]); |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * @param array $aServerParams The server environment variables |
||
89 | * |
||
90 | * @return void |
||
91 | * @throws UriException |
||
92 | */ |
||
93 | private function setHost(array $aServerParams): void |
||
105 | } |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * @param array $aServerParams The server environment variables |
||
110 | * |
||
111 | * @return void |
||
112 | */ |
||
113 | private function setPath(array $aServerParams): void |
||
114 | { |
||
115 | if(isset($this->aUrl['path']) && strlen(basename($this->aUrl['path'])) === 0) |
||
116 | { |
||
117 | unset($this->aUrl['path']); |
||
118 | } |
||
119 | if(isset($this->aUrl['path'])) |
||
120 | { |
||
121 | return; |
||
122 | } |
||
123 | $aPath = parse_url($aServerParams['PATH_INFO'] ?? ($aServerParams['PHP_SELF'] ?? '')); |
||
124 | if(isset($aPath['path'])) |
||
125 | { |
||
126 | $this->aUrl['path'] = $aPath['path']; |
||
127 | } |
||
128 | } |
||
129 | |||
130 | /** |
||
131 | * @return string |
||
132 | */ |
||
133 | private function getPath(): string |
||
134 | { |
||
135 | return '/' . ltrim($this->aUrl['path'], '/'); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * @return string |
||
140 | */ |
||
141 | private function getUser(): string |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * @return string |
||
157 | */ |
||
158 | private function getPort(): string |
||
159 | { |
||
160 | if(isset($this->aUrl['port']) && |
||
161 | (($this->aUrl['scheme'] === 'http' && $this->aUrl['port'] != 80) || |
||
162 | ($this->aUrl['scheme'] === 'https' && $this->aUrl['port'] != 443))) |
||
163 | { |
||
164 | return ':' . $this->aUrl['port']; |
||
165 | } |
||
166 | return ''; |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * @param array $aServerParams The server environment variables |
||
171 | * |
||
172 | * @return void |
||
173 | */ |
||
174 | private function setQuery(array $aServerParams): void |
||
179 | } |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * @return string |
||
184 | */ |
||
185 | private function getQuery(): string |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * Detect the URI of the current request |
||
208 | * |
||
209 | * @param array $aServerParams The server environment variables |
||
210 | * |
||
211 | * @return string |
||
212 | * @throws UriException |
||
213 | */ |
||
214 | public function detect(array $aServerParams): string |
||
215 | { |
||
216 | $this->aUrl = []; |
||
217 | // Try to get the request URL |
||
218 | if(isset($aServerParams['REQUEST_URI'])) |
||
219 | { |
||
220 | $this->aUrl = parse_url($aServerParams['REQUEST_URI']); |
||
221 | } |
||
222 | |||
223 | // Fill in the empty values |
||
224 | $this->setScheme($aServerParams); |
||
225 | $this->setHost($aServerParams); |
||
226 | $this->setPath($aServerParams); |
||
227 | $this->setQuery($aServerParams); |
||
228 | |||
229 | // Build the URL: Start with scheme, user and pass |
||
230 | return $this->aUrl['scheme'] . '://' . $this->getUser() . $this->aUrl['host'] . |
||
231 | $this->getPort() . str_replace(['"', "'", '<', '>'], |
||
232 | ['%22', '%27', '%3C', '%3E'], $this->getPath() . $this->getQuery()); |
||
233 | } |
||
234 | |||
235 | /** |
||
236 | * @param string $sQueryPart |
||
237 | * @param string $sKey |
||
238 | * @param string $sValue |
||
239 | * |
||
240 | * @return string |
||
241 | */ |
||
242 | private function makeQueryPart(string $sQueryPart, string $sKey, string $sValue): string |
||
243 | { |
||
244 | return $sValue === '' && strpos($sQueryPart, "$sKey=") === false ? |
||
245 | rawurlencode($sKey) : rawurlencode($sKey) . '=' . rawurlencode($sValue); |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * @param string $sQueryPart |
||
250 | * @param array $aServerParams |
||
251 | * |
||
252 | * @return string |
||
253 | */ |
||
254 | private function parseQueryPart(string $sQueryPart, array $aServerParams): string |
||
255 | { |
||
256 | $aQueryParts = []; |
||
257 | parse_str($sQueryPart, $aQueryParts); |
||
258 | if(empty($aQueryParts)) |
||
259 | { |
||
260 | // Couldn't break up the query, but there's one there. |
||
261 | // Possibly "http://url/page.html?query1234" type of query? |
||
262 | // Try to get data from the server environment var. |
||
263 | parse_str($aServerParams['QUERY_STRING'] ?? '', $aQueryParts); |
||
264 | } |
||
265 | if(($aQueryParts)) |
||
266 | { |
||
267 | $aNewQueryParts = []; |
||
268 | foreach($aQueryParts as $sKey => $sValue) |
||
269 | { |
||
270 | $aNewQueryParts[] = $this->makeQueryPart($sQueryPart, $sKey, $sValue); |
||
271 | } |
||
272 | return '?' . implode('&', $aNewQueryParts); |
||
273 | } |
||
274 | return trim($sQueryPart); |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Make the specified URL suitable for redirect |
||
279 | * |
||
280 | * @param string $sURL The relative or fully qualified URL |
||
281 | * @param array $aServerParams The server environment variables |
||
282 | * |
||
283 | * @return string |
||
284 | */ |
||
285 | public function redirect(string $sURL, array $aServerParams): string |
||
303 | } |
||
304 | } |
||
305 |