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 |