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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 |
||
11 | class Request extends ServerRequest |
||
12 | { |
||
13 | /** |
||
14 | * Create an instance from globals |
||
15 | * |
||
16 | * @param array $server |
||
17 | * @param array $query |
||
18 | * @param array $body |
||
19 | * @param array $cookies |
||
20 | * @param array $files |
||
21 | * @return Request |
||
22 | */ |
||
23 | public static function fromGlobals( |
||
24 | array $server = null, |
||
25 | array $query = null, |
||
26 | array $body = null, |
||
27 | array $cookies = null, |
||
28 | array $files = null |
||
29 | ) { |
||
30 | $server = \Zend\Diactoros\normalizeServer($server ?: $_SERVER); |
||
31 | $files = \Zend\Diactoros\normalizeUploadedFiles($files ?: $_FILES); |
||
32 | $headers = \Zend\Diactoros\marshalHeadersFromSapi($server); |
||
33 | $method = \Zend\Diactoros\marshalMethodFromSapi($server); |
||
34 | $uri = \Zend\Diactoros\marshalUriFromSapi($server, $headers); |
||
35 | |||
36 | if (null === $cookies && array_key_exists('cookie', $headers)) { |
||
37 | $cookies = self::parseCookieHeader($headers['cookie']); |
||
38 | } |
||
39 | |||
40 | |||
41 | if ($body === null) { |
||
42 | $body = []; |
||
43 | if (isset($headers['content-type']) && strpos($headers['content-type'], 'json') !== false) { |
||
44 | $body = json_decode($body, true); |
||
45 | if ($body === null) { |
||
46 | $body = []; |
||
47 | } |
||
48 | } else { |
||
49 | $body = static::fixedQueryParams(file_get_contents('php://input')); |
||
50 | } |
||
51 | } |
||
52 | |||
53 | return new static( |
||
54 | $server, |
||
55 | $files, |
||
56 | $uri, |
||
57 | $method, |
||
58 | 'php://input', |
||
59 | $headers, |
||
60 | $cookies ?: $_COOKIE, |
||
61 | $query ?: static::fixedQueryParams($uri->getQuery()), |
||
62 | $body ?: (count($_POST) ? $_POST : json_decode(file_get_contents('php://input'), true)), |
||
63 | \Zend\Diactoros\marshalProtocolVersionFromSapi($server) |
||
64 | ); |
||
65 | } |
||
66 | 1 | public static function fromString(string $str) : Request |
|
305 | 1 | protected function getValue(array $collection, $key, $default, $mode) |
|
306 | { |
||
307 | 1 | if ($key === null) { |
|
308 | return $this->cleanValue($collection, $mode); |
||
309 | } |
||
310 | 1 | return isset($collection[$key]) ? $this->cleanValue($collection[$key], $mode) : $default; |
|
311 | } |
||
312 | /** |
||
313 | * Gets a value from a cookie that came with the request |
||
314 | * @param string $key the cookie name |
||
315 | * @param mixed $default optional default value to return if the key is not present (default to `null`) |
||
316 | * @param string $mode optional cleanup of the value, available modes are: int, float, nohtml, escape, string |
||
317 | * @return mixed the value (or values) |
||
318 | */ |
||
319 | 1 | public function getCookie($key = null, $default = null, $mode = null) |
|
320 | { |
||
321 | 1 | return $this->getValue($this->getCookieParams(), $key, $default, $mode); |
|
322 | } |
||
323 | /** |
||
324 | * Get a GET param from the request URL |
||
325 | * @param string $key the GET param name |
||
326 | * @param mixed $default optional default value to return if the key is not present (default to `null`) |
||
327 | * @param string $mode optional cleanup of the value, available modes are: int, float, nohtml, escape, string |
||
328 | * @return mixed the value (or values) |
||
329 | */ |
||
330 | 1 | public function getQuery($key = null, $default = null, $mode = null) |
|
331 | { |
||
332 | 1 | return $this->getValue($this->getQueryParams(), $key, $default, $mode); |
|
333 | } |
||
334 | /** |
||
335 | * Get a param from the request body (if it is in JSON format it will be parsed out as well) |
||
336 | * @param string $key the param name |
||
337 | * @param mixed $default optional default value to return if the key is not present (default to `null`) |
||
338 | * @param string $mode optional cleanup of the value, available modes are: int, float, nohtml, escape, string |
||
339 | * @return mixed the value (or values if no key was specified) |
||
340 | */ |
||
341 | public function getPost($key = null, $default = null, $mode = null) |
||
342 | { |
||
343 | $body = $this->getParsedBody(); |
||
344 | if (!is_array($body)) { |
||
345 | $body = []; |
||
346 | } |
||
347 | return $this->getValue($body, $key, $default, $mode); |
||
348 | } |
||
349 | /** |
||
350 | * Get any authorization details supplied with the request. |
||
351 | * @return array|null array of extracted values or null (possible keys are username, password and token) |
||
352 | */ |
||
353 | public function getAuthorization() |
||
372 | public function getUrl() |
||
373 | { |
||
374 | return $this->getUri(); |
||
375 | } |
||
376 | /** |
||
377 | * Determine if this is an AJAX request |
||
378 | * @return boolean is the request AJAX |
||
379 | */ |
||
380 | 1 | public function isAjax() |
|
384 | /** |
||
385 | * Determine if this is an CORS request |
||
386 | * @return boolean is the request CORS |
||
387 | */ |
||
388 | 1 | public function isCors() |
|
402 | /** |
||
403 | * Get the prefered response languages (parses the Accept-Language header if present). |
||
404 | * @param bool $shortNames should values like "en-US", be truncated to "en", defaults to true |
||
405 | * @return array array of ordered lowercase language codes |
||
406 | */ |
||
407 | 1 | public function getPreferredResponseLanguages(bool $shortNames = true) : array |
|
435 | /** |
||
436 | * Get the preffered response language (parses the Accept-Language header if present). |
||
437 | * @param string $default the default code to return if the header is not found |
||
438 | * @param array|null $allowed an optional list of lowercase language codes to intersect with, defaults to null |
||
439 | * @return string the prefered language code |
||
440 | */ |
||
441 | 1 | public function getPreferredResponseLanguage(string $default = 'en', array $allowed = null) : string |
|
454 | /** |
||
455 | * Get the prefered response formats. |
||
456 | * @param string $default the default value to return if the Accept header is not present. |
||
457 | * @return string[] the desired response formats |
||
458 | */ |
||
459 | 1 | public function getPreferredResponseFormats($default = 'text/html') |
|
488 | /** |
||
489 | * Get the preffered response language (parses the Accept-Language header if present). |
||
490 | * @param string $default the default code to return if the header is not found |
||
491 | * @param array|null $allowed an optional list of lowercase language codes to intersect with, defaults to null |
||
492 | * @return string the prefered language code |
||
493 | */ |
||
494 | 1 | public function getPreferredResponseFormat(string $default = 'text/html', array $allowed = null) : string |
|
508 | } |
||
509 |