1<?php 2/** 3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository 4 * @copyright Copyright (c) 2015-2017 Zend Technologies USA Inc. (http://www.zend.com) 5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License 6 */ 7 8namespace Zend\Diactoros; 9 10use InvalidArgumentException; 11use Psr\Http\Message\UploadedFileInterface; 12use stdClass; 13use UnexpectedValueException; 14 15use function array_change_key_case; 16use function array_key_exists; 17use function explode; 18use function implode; 19use function is_array; 20use function is_callable; 21use function strtolower; 22 23use const CASE_LOWER; 24 25/** 26 * Class for marshaling a request object from the current PHP environment. 27 * 28 * Logic largely refactored from the ZF2 Zend\Http\PhpEnvironment\Request class. 29 * 30 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 31 * @license http://framework.zend.com/license/new-bsd New BSD License 32 */ 33abstract class ServerRequestFactory 34{ 35 /** 36 * Function to use to get apache request headers; present only to simplify mocking. 37 * 38 * @var callable 39 */ 40 private static $apacheRequestHeaders = 'apache_request_headers'; 41 42 /** 43 * Create a request from the supplied superglobal values. 44 * 45 * If any argument is not supplied, the corresponding superglobal value will 46 * be used. 47 * 48 * The ServerRequest created is then passed to the fromServer() method in 49 * order to marshal the request URI and headers. 50 * 51 * @see fromServer() 52 * @param array $server $_SERVER superglobal 53 * @param array $query $_GET superglobal 54 * @param array $body $_POST superglobal 55 * @param array $cookies $_COOKIE superglobal 56 * @param array $files $_FILES superglobal 57 * @return ServerRequest 58 * @throws InvalidArgumentException for invalid file values 59 */ 60 public static function fromGlobals( 61 array $server = null, 62 array $query = null, 63 array $body = null, 64 array $cookies = null, 65 array $files = null 66 ) { 67 $server = normalizeServer( 68 $server ?: $_SERVER, 69 is_callable(self::$apacheRequestHeaders) ? self::$apacheRequestHeaders : null 70 ); 71 $files = normalizeUploadedFiles($files ?: $_FILES); 72 $headers = marshalHeadersFromSapi($server); 73 74 if (null === $cookies && array_key_exists('cookie', $headers)) { 75 $cookies = parseCookieHeader($headers['cookie']); 76 } 77 78 return new ServerRequest( 79 $server, 80 $files, 81 marshalUriFromSapi($server, $headers), 82 marshalMethodFromSapi($server), 83 'php://input', 84 $headers, 85 $cookies ?: $_COOKIE, 86 $query ?: $_GET, 87 $body ?: $_POST, 88 marshalProtocolVersionFromSapi($server) 89 ); 90 } 91 92 /** 93 * Access a value in an array, returning a default value if not found 94 * 95 * @deprecated since 1.8.0; no longer used internally. 96 * @param string $key 97 * @param array $values 98 * @param mixed $default 99 * @return mixed 100 */ 101 public static function get($key, array $values, $default = null) 102 { 103 if (array_key_exists($key, $values)) { 104 return $values[$key]; 105 } 106 107 return $default; 108 } 109 110 /** 111 * Search for a header value. 112 * 113 * Does a case-insensitive search for a matching header. 114 * 115 * If found, it is returned as a string, using comma concatenation. 116 * 117 * If not, the $default is returned. 118 * 119 * @deprecated since 1.8.0; no longer used internally. 120 * @param string $header 121 * @param array $headers 122 * @param mixed $default 123 * @return string 124 */ 125 public static function getHeader($header, array $headers, $default = null) 126 { 127 $header = strtolower($header); 128 $headers = array_change_key_case($headers, CASE_LOWER); 129 if (array_key_exists($header, $headers)) { 130 $value = is_array($headers[$header]) ? implode(', ', $headers[$header]) : $headers[$header]; 131 return $value; 132 } 133 134 return $default; 135 } 136 137 /** 138 * Marshal the $_SERVER array 139 * 140 * Pre-processes and returns the $_SERVER superglobal. 141 * 142 * @deprected since 1.8.0; use Zend\Diactoros\normalizeServer() instead. 143 * @param array $server 144 * @return array 145 */ 146 public static function normalizeServer(array $server) 147 { 148 return normalizeServer( 149 $server ?: $_SERVER, 150 is_callable(self::$apacheRequestHeaders) ? self::$apacheRequestHeaders : null 151 ); 152 } 153 154 /** 155 * Normalize uploaded files 156 * 157 * Transforms each value into an UploadedFileInterface instance, and ensures 158 * that nested arrays are normalized. 159 * 160 * @deprecated since 1.8.0; use \Zend\Diactoros\normalizeUploadedFiles instead. 161 * @param array $files 162 * @return array 163 * @throws InvalidArgumentException for unrecognized values 164 */ 165 public static function normalizeFiles(array $files) 166 { 167 return normalizeUploadedFiles($files); 168 } 169 170 /** 171 * Marshal headers from $_SERVER 172 * 173 * @deprecated since 1.8.0; use Zend\Diactoros\marshalHeadersFromSapi(). 174 * @param array $server 175 * @return array 176 */ 177 public static function marshalHeaders(array $server) 178 { 179 return marshalHeadersFromSapi($server); 180 } 181 182 /** 183 * Marshal the URI from the $_SERVER array and headers 184 * 185 * @deprecated since 1.8.0; use Zend\Diactoros\marshalUriFromSapi() instead. 186 * @param array $server 187 * @param array $headers 188 * @return Uri 189 */ 190 public static function marshalUriFromServer(array $server, array $headers) 191 { 192 return marshalUriFromSapi($server, $headers); 193 } 194 195 /** 196 * Marshal the host and port from HTTP headers and/or the PHP environment 197 * 198 * @deprecated since 1.8.0; use Zend\Diactoros\marshalUriFromSapi() instead, 199 * and pull the host and port from the Uri instance that function 200 * returns. 201 * @param stdClass $accumulator 202 * @param array $server 203 * @param array $headers 204 */ 205 public static function marshalHostAndPortFromHeaders(stdClass $accumulator, array $server, array $headers) 206 { 207 $uri = marshalUriFromSapi($server, $headers); 208 $accumulator->host = $uri->getHost(); 209 $accumulator->port = $uri->getPort(); 210 } 211 212 /** 213 * Detect the base URI for the request 214 * 215 * Looks at a variety of criteria in order to attempt to autodetect a base 216 * URI, including rewrite URIs, proxy URIs, etc. 217 * 218 * @deprecated since 1.8.0; use Zend\Diactoros\marshalUriFromSapi() instead, 219 * and pull the path from the Uri instance that function returns. 220 * @param array $server 221 * @return string 222 */ 223 public static function marshalRequestUri(array $server) 224 { 225 $uri = marshalUriFromSapi($server, []); 226 return $uri->getPath(); 227 } 228 229 /** 230 * Strip the query string from a path 231 * 232 * @deprecated since 1.8.0; no longer used internally. 233 * @param mixed $path 234 * @return string 235 */ 236 public static function stripQueryString($path) 237 { 238 return explode('?', $path, 2)[0]; 239 } 240} 241