Total Complexity | 59 |
Total Lines | 536 |
Duplicated Lines | 0 % |
Changes | 4 | ||
Bugs | 0 | Features | 0 |
Complex classes like Request 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 Request, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | class Request |
||
23 | { |
||
24 | /** |
||
25 | * Request data types to be treated case-insensitively. |
||
26 | * |
||
27 | * @var array |
||
28 | */ |
||
29 | protected static $caseInsensitive = array('server', 'header'); |
||
30 | |||
31 | /** |
||
32 | * The request data. |
||
33 | * |
||
34 | * @var array |
||
35 | */ |
||
36 | protected $data = array( |
||
37 | 'get' => array(), |
||
38 | 'post' => array(), |
||
39 | 'cookie' => array(), |
||
40 | 'file' => array(), |
||
41 | 'server' => array(), |
||
42 | 'header' => array(), |
||
43 | 'session' => null |
||
44 | ); |
||
45 | |||
46 | /** |
||
47 | * Request body content. |
||
48 | * |
||
49 | * @var string |
||
50 | */ |
||
51 | protected $content; |
||
52 | |||
53 | /** |
||
54 | * The session that belongs to this request. |
||
55 | * |
||
56 | * @var \Darya\Http\Session |
||
57 | */ |
||
58 | protected $session; |
||
59 | |||
60 | /** |
||
61 | * The router that matched this request. |
||
62 | * |
||
63 | * @var \Darya\Routing\Router |
||
64 | */ |
||
65 | public $router; |
||
66 | |||
67 | /** |
||
68 | * The route that this request was matched with. |
||
69 | * |
||
70 | * @var \Darya\Routing\Route |
||
71 | */ |
||
72 | public $route; |
||
73 | |||
74 | /** |
||
75 | * Determine whether the given data type's keys can be treated |
||
76 | * case-insensitively. |
||
77 | * |
||
78 | * @param string $type |
||
79 | * @return bool |
||
80 | */ |
||
81 | protected static function isCaseInsensitive($type) |
||
82 | { |
||
83 | return in_array($type, static::$caseInsensitive); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Prepare the given request data where necessary. |
||
88 | * |
||
89 | * Lowercases data type keys and the keys of `server` and `header` data so |
||
90 | * they can be treated case-insensitively. |
||
91 | * |
||
92 | * Any expected data types not satisfied will contain an empty array apart |
||
93 | * from `session`, which will be null. |
||
94 | * |
||
95 | * @param array $data |
||
96 | * @return array |
||
97 | */ |
||
98 | protected static function prepareData(array $data) |
||
99 | { |
||
100 | $data = array_change_key_case($data); |
||
101 | |||
102 | foreach (array_keys($data) as $type) { |
||
103 | if (static::isCaseInsensitive($type)) { |
||
104 | $data[$type] = array_change_key_case($data[$type]); |
||
105 | } |
||
106 | } |
||
107 | |||
108 | return array_merge(array( |
||
109 | 'get' => array(), |
||
110 | 'post' => array(), |
||
111 | 'cookie' => array(), |
||
112 | 'file' => array(), |
||
113 | 'server' => array(), |
||
114 | 'header' => array(), |
||
115 | 'session' => null |
||
116 | ), $data); |
||
117 | } |
||
118 | |||
119 | |||
120 | /** |
||
121 | * Parse the given URI and return its components. |
||
122 | * |
||
123 | * Any components not satisfied will be null instead of non-existent, so you |
||
124 | * can safely expect the keys 'scheme', 'host', 'port', 'user', 'pass', |
||
125 | * 'query' and 'fragment' to exist. |
||
126 | * |
||
127 | * @param string $url |
||
128 | * @return array |
||
129 | */ |
||
130 | protected static function parseUrl($url) |
||
131 | { |
||
132 | $components = parse_url($url); |
||
133 | |||
134 | return array_merge(array( |
||
135 | 'scheme' => null, |
||
136 | 'host' => null, |
||
137 | 'port' => null, |
||
138 | 'user' => null, |
||
139 | 'pass' => null, |
||
140 | 'path' => null, |
||
141 | 'query' => null, |
||
142 | 'fragment' => null |
||
143 | ), $components ?: array()); |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * Parse the given query string and return its key value pairs. |
||
148 | * |
||
149 | * @param string $query |
||
150 | * @return array |
||
151 | */ |
||
152 | protected static function parseQuery($query) |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * Create a new request with the given URL, method and data. |
||
162 | * |
||
163 | * @param string $url |
||
164 | * @param string $method [optional] |
||
165 | * @param array $data [optional] |
||
166 | * @param Session $session [optional] |
||
167 | * @return Request |
||
168 | */ |
||
169 | public static function create($url, $method = 'GET', $data = array(), Session $session = null) |
||
170 | { |
||
171 | $components = static::parseUrl($url); |
||
172 | $data = static::prepareData($data); |
||
173 | |||
174 | $data['get'] = array_merge( |
||
175 | $data['get'], |
||
176 | static::parseQuery($components['query']) |
||
177 | ); |
||
178 | |||
179 | if ($components['host']) { |
||
180 | $data['server']['http_host'] = $components['host']; |
||
181 | $data['server']['server_name'] = $components['host']; |
||
182 | } |
||
183 | |||
184 | if ($components['path']) { |
||
185 | $data['server']['path_info'] = $components['path']; |
||
186 | $data['server']['request_uri'] = $components['path']; |
||
187 | } |
||
188 | |||
189 | $data['server']['request_method'] = strtoupper($method); |
||
190 | |||
191 | if ($components['query']) { |
||
192 | $data['server']['request_uri'] .= '?' . $components['query']; |
||
193 | } |
||
194 | |||
195 | $request = new Request( |
||
196 | $data['get'], |
||
197 | $data['post'], |
||
198 | $data['cookie'], |
||
199 | $data['file'], |
||
200 | $data['server'], |
||
201 | $data['header'] |
||
202 | ); |
||
203 | |||
204 | $request->setSession($session); |
||
205 | |||
206 | return $request; |
||
207 | } |
||
208 | |||
209 | |||
210 | /** |
||
211 | * Extract HTTP request headers from a given set of $_SERVER globals. |
||
212 | * |
||
213 | * @param array $server |
||
214 | * @return array |
||
215 | */ |
||
216 | public static function headersFromGlobals(array $server) |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * Create a new request using PHP's super globals. |
||
234 | * |
||
235 | * @param \Darya\Http\Session $session [optional] |
||
236 | * @return \Darya\Http\Request |
||
237 | */ |
||
238 | public static function createFromGlobals(Session $session = null) |
||
239 | { |
||
240 | $request = Request::create($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD'], array( |
||
241 | 'get' => $_GET, |
||
242 | 'post' => $_POST, |
||
243 | 'cookie' => $_COOKIE, |
||
244 | 'file' => $_FILES, |
||
245 | 'server' => $_SERVER, |
||
246 | 'header' => static::headersFromGlobals($_SERVER) |
||
247 | ), $session); |
||
248 | |||
249 | return $request; |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Instantiate a new request with the given data. |
||
254 | * |
||
255 | * Expects request data in the same format as PHP superglobals. |
||
256 | * |
||
257 | * @param array $get |
||
258 | * @param array $post |
||
259 | * @param array $cookie |
||
260 | * @param array $file |
||
261 | * @param array $server |
||
262 | * @param array $header |
||
263 | */ |
||
264 | public function __construct(array $get, array $post, array $cookie, array $file, array $server, array $header) |
||
265 | { |
||
266 | $this->data = static::prepareData(compact('get', 'post', 'cookie', 'file', 'server', 'header')); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Determine whether this Request has a session interface. |
||
271 | * |
||
272 | * @return bool |
||
273 | */ |
||
274 | public function hasSession() |
||
275 | { |
||
276 | return !is_null($this->session); |
||
277 | } |
||
278 | |||
279 | /** |
||
280 | * Set the session interface for the request. Starts the session if it |
||
281 | * hasn't been already. |
||
282 | * |
||
283 | * @param \Darya\Http\Session $session |
||
284 | */ |
||
285 | public function setSession(Session $session = null) |
||
286 | { |
||
287 | if (is_object($session) && !$session->started()) { |
||
288 | $session->start(); |
||
289 | } |
||
290 | |||
291 | $this->session = $session; |
||
292 | $this->data['session'] = $this->session; |
||
293 | } |
||
294 | |||
295 | /** |
||
296 | * Retrieve request data of the given type using the given key. |
||
297 | * |
||
298 | * If $key is not set, all request data of the given type will be returned. |
||
299 | * |
||
300 | * If neither $type or $key are set, all request data will be returned. |
||
301 | * |
||
302 | * If a $default value is given along with $key, it is returned if $key is |
||
303 | * not set in the data of the given $type. |
||
304 | * |
||
305 | * @param string $type [optional] |
||
306 | * @param string $key [optional] |
||
307 | * @param mixed $default [optional] |
||
308 | * @return mixed |
||
309 | */ |
||
310 | public function data($type = null, $key = null, $default = null) |
||
311 | { |
||
312 | $type = strtolower($type); |
||
|
|||
313 | |||
314 | if (isset($this->data[$type])) { |
||
315 | if (static::isCaseInsensitive($type)) { |
||
316 | $key = strtolower($key); |
||
317 | } |
||
318 | |||
319 | if (!empty($key)) { |
||
320 | return isset($this->data[$type][$key]) ? $this->data[$type][$key] : $default; |
||
321 | } |
||
322 | |||
323 | return $this->data[$type]; |
||
324 | } |
||
325 | |||
326 | return $this->data; |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * Dynamically retrieve all request data of the given type. |
||
331 | * |
||
332 | * @param string $property |
||
333 | * @return array |
||
334 | */ |
||
335 | public function __get($property) |
||
336 | { |
||
337 | return $this->data($property); |
||
338 | } |
||
339 | |||
340 | /** |
||
341 | * Dynamically retrieve request data. |
||
342 | * |
||
343 | * @param string $method |
||
344 | * @param array $arguments |
||
345 | */ |
||
346 | public function __call($method, $arguments) |
||
347 | { |
||
348 | $arguments = array_merge(array($method), array_slice($arguments, 0, 2)); |
||
349 | |||
350 | return call_user_func_array(array($this, 'data'), $arguments); |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * Determine whether a given parameter is set in the request's post or get |
||
355 | * data. |
||
356 | * |
||
357 | * @param string $key |
||
358 | * @return bool |
||
359 | */ |
||
360 | public function has($key) |
||
361 | { |
||
362 | return isset($this->data['get'][$key]) || isset($this->data['post'][$key]); |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Retrieve a parameter from either the post or get data of the request, |
||
367 | * checking post data if the request method is post. |
||
368 | * |
||
369 | * @param string $key |
||
370 | * @return mixed |
||
371 | */ |
||
372 | public function any($key = null) |
||
373 | { |
||
374 | return $this->method('post') && isset($this->data['post'][$key]) ? $this->post($key) : $this->get($key); |
||
375 | } |
||
376 | |||
377 | /** |
||
378 | * Retrieve the URI of the request. |
||
379 | * |
||
380 | * @return string |
||
381 | */ |
||
382 | public function uri() |
||
383 | { |
||
384 | return $this->server('request_uri'); |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * Retrieve the hostname of the request. |
||
389 | * |
||
390 | * @return string |
||
391 | */ |
||
392 | public function host() |
||
393 | { |
||
394 | return $this->server('server_name') ?: $this->server('server_addr'); |
||
395 | } |
||
396 | |||
397 | /** |
||
398 | * Retrieve the path of the request. |
||
399 | * |
||
400 | * @return string |
||
401 | */ |
||
402 | public function path() |
||
403 | { |
||
404 | $path = $this->server('path_info'); |
||
405 | |||
406 | if ($path) { |
||
407 | return $path; |
||
408 | } |
||
409 | |||
410 | $components = static::parseUrl($this->uri()); |
||
411 | |||
412 | return $components['path']; |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * Retrieve the method of the request or determine whether the method of the |
||
417 | * request is the same as the one given. |
||
418 | * |
||
419 | * @param string $method [optional] |
||
420 | * @return string|bool |
||
421 | */ |
||
422 | public function method($method = null) |
||
423 | { |
||
424 | $method = strtolower($method); |
||
425 | $requestMethod = strtolower($this->server('request_method')); |
||
426 | |||
427 | return $method ? $requestMethod == $method : $this->server('request_method'); |
||
428 | } |
||
429 | |||
430 | /** |
||
431 | * Retrieve the request body. |
||
432 | * |
||
433 | * @return string |
||
434 | */ |
||
435 | public function body() |
||
436 | { |
||
437 | return $this->content(); |
||
438 | } |
||
439 | |||
440 | /** |
||
441 | * Retrieve the request body. |
||
442 | * |
||
443 | * @return string |
||
444 | */ |
||
445 | public function content() |
||
446 | { |
||
447 | if ($this->content === null) { |
||
448 | $this->content = file_get_contents('php://input'); |
||
449 | } |
||
450 | |||
451 | return $this->content; |
||
452 | } |
||
453 | |||
454 | /** |
||
455 | * Retrieve the IP address of the client that made the request. |
||
456 | * |
||
457 | * @return string |
||
458 | */ |
||
459 | public function ip() |
||
460 | { |
||
461 | return $this->server('remote_addr'); |
||
462 | } |
||
463 | |||
464 | /** |
||
465 | * Determine whether this is an ajax Request. This is determined by 'get' or |
||
466 | * 'post' data having an ajax parameter set or the 'X-Requested-With' |
||
467 | * parameter having the 'XMLHttpRequest' value. |
||
468 | * |
||
469 | * @return bool |
||
470 | */ |
||
471 | public function ajax() |
||
476 | } |
||
477 | |||
478 | /** |
||
479 | * Flash data with the given key to the session. |
||
480 | * |
||
481 | * @param string $key Flash data key |
||
482 | * @param string|array $values A single value or set of values to add |
||
483 | * @return bool |
||
484 | */ |
||
485 | public function flash($key, $values) |
||
502 | } |
||
503 | |||
504 | /** |
||
505 | * Retrieve and clear flashed data with the given key from the session. If |
||
506 | * no key is given, all data is retrieved and cleared. |
||
507 | * |
||
508 | * Returns an empty array if this request has no session or flash variables |
||
509 | * were not found with the given key. |
||
510 | * |
||
511 | * @param string $key [optional] Flash data key |
||
512 | * @return array |
||
513 | */ |
||
514 | public function flashes($key = null) |
||
515 | { |
||
516 | $data = array(); |
||
517 | |||
518 | if ($this->hasSession()) { |
||
519 | $flash = $this->session->get('flash'); |
||
520 | |||
521 | if (!empty($key)) { |
||
522 | if (isset($flash[$key])) { |
||
523 | $data = $flash[$key]; |
||
524 | unset($flash[$key]); |
||
525 | } |
||
526 | } else { |
||
527 | $data = $flash; |
||
528 | $flash = array(); |
||
529 | } |
||
530 | |||
531 | $this->session->set('flash', $flash); |
||
532 | } |
||
533 | |||
534 | return $data; |
||
535 | } |
||
536 | |||
537 | /** |
||
538 | * Transforms post request data of the form entity[property][n] to the form |
||
539 | * entity[n][property]. |
||
540 | * |
||
541 | * @param string $key Entity key (post parameter name) |
||
542 | * @return array |
||
543 | */ |
||
544 | public function postObjectData($key = null) |
||
558 | } |
||
559 | } |
||
560 |