Chris@0: serverParams = $serverParams; Chris@0: Chris@0: parent::__construct($method, $uri, $headers, $body, $version); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Return an UploadedFile instance array. Chris@0: * Chris@0: * @param array $files A array which respect $_FILES structure Chris@0: * @throws InvalidArgumentException for unrecognized values Chris@0: * @return array Chris@0: */ Chris@0: public static function normalizeFiles(array $files) Chris@0: { Chris@0: $normalized = []; Chris@0: Chris@0: foreach ($files as $key => $value) { Chris@0: if ($value instanceof UploadedFileInterface) { Chris@0: $normalized[$key] = $value; Chris@0: } elseif (is_array($value) && isset($value['tmp_name'])) { Chris@0: $normalized[$key] = self::createUploadedFileFromSpec($value); Chris@0: } elseif (is_array($value)) { Chris@0: $normalized[$key] = self::normalizeFiles($value); Chris@0: continue; Chris@0: } else { Chris@0: throw new InvalidArgumentException('Invalid value in files specification'); Chris@0: } Chris@0: } Chris@0: Chris@0: return $normalized; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Create and return an UploadedFile instance from a $_FILES specification. Chris@0: * Chris@0: * If the specification represents an array of values, this method will Chris@0: * delegate to normalizeNestedFileSpec() and return that return value. Chris@0: * Chris@0: * @param array $value $_FILES struct Chris@0: * @return array|UploadedFileInterface Chris@0: */ Chris@0: private static function createUploadedFileFromSpec(array $value) Chris@0: { Chris@0: if (is_array($value['tmp_name'])) { Chris@0: return self::normalizeNestedFileSpec($value); Chris@0: } Chris@0: Chris@0: return new UploadedFile( Chris@0: $value['tmp_name'], Chris@0: (int) $value['size'], Chris@0: (int) $value['error'], Chris@0: $value['name'], Chris@0: $value['type'] Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Normalize an array of file specifications. Chris@0: * Chris@0: * Loops through all nested files and returns a normalized array of Chris@0: * UploadedFileInterface instances. Chris@0: * Chris@0: * @param array $files Chris@0: * @return UploadedFileInterface[] Chris@0: */ Chris@0: private static function normalizeNestedFileSpec(array $files = []) Chris@0: { Chris@0: $normalizedFiles = []; Chris@0: Chris@0: foreach (array_keys($files['tmp_name']) as $key) { Chris@0: $spec = [ Chris@0: 'tmp_name' => $files['tmp_name'][$key], Chris@0: 'size' => $files['size'][$key], Chris@0: 'error' => $files['error'][$key], Chris@0: 'name' => $files['name'][$key], Chris@0: 'type' => $files['type'][$key], Chris@0: ]; Chris@0: $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); Chris@0: } Chris@0: Chris@0: return $normalizedFiles; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Return a ServerRequest populated with superglobals: Chris@0: * $_GET Chris@0: * $_POST Chris@0: * $_COOKIE Chris@0: * $_FILES Chris@0: * $_SERVER Chris@0: * Chris@0: * @return ServerRequestInterface Chris@0: */ Chris@0: public static function fromGlobals() Chris@0: { Chris@0: $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'; Chris@17: $headers = getallheaders(); Chris@0: $uri = self::getUriFromGlobals(); Chris@0: $body = new LazyOpenStream('php://input', 'r+'); Chris@0: $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; Chris@0: Chris@0: $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); Chris@0: Chris@0: return $serverRequest Chris@0: ->withCookieParams($_COOKIE) Chris@0: ->withQueryParams($_GET) Chris@0: ->withParsedBody($_POST) Chris@0: ->withUploadedFiles(self::normalizeFiles($_FILES)); Chris@0: } Chris@0: Chris@17: private static function extractHostAndPortFromAuthority($authority) Chris@17: { Chris@17: $uri = 'http://'.$authority; Chris@17: $parts = parse_url($uri); Chris@17: if (false === $parts) { Chris@17: return [null, null]; Chris@17: } Chris@17: Chris@17: $host = isset($parts['host']) ? $parts['host'] : null; Chris@17: $port = isset($parts['port']) ? $parts['port'] : null; Chris@17: Chris@17: return [$host, $port]; Chris@17: } Chris@17: Chris@0: /** Chris@0: * Get a Uri populated with values from $_SERVER. Chris@0: * Chris@0: * @return UriInterface Chris@0: */ Chris@17: public static function getUriFromGlobals() Chris@17: { Chris@0: $uri = new Uri(''); Chris@0: Chris@0: $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); Chris@0: Chris@0: $hasPort = false; Chris@0: if (isset($_SERVER['HTTP_HOST'])) { Chris@17: list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); Chris@17: if ($host !== null) { Chris@17: $uri = $uri->withHost($host); Chris@17: } Chris@17: Chris@17: if ($port !== null) { Chris@0: $hasPort = true; Chris@17: $uri = $uri->withPort($port); Chris@0: } Chris@0: } elseif (isset($_SERVER['SERVER_NAME'])) { Chris@0: $uri = $uri->withHost($_SERVER['SERVER_NAME']); Chris@0: } elseif (isset($_SERVER['SERVER_ADDR'])) { Chris@0: $uri = $uri->withHost($_SERVER['SERVER_ADDR']); Chris@0: } Chris@0: Chris@0: if (!$hasPort && isset($_SERVER['SERVER_PORT'])) { Chris@0: $uri = $uri->withPort($_SERVER['SERVER_PORT']); Chris@0: } Chris@0: Chris@0: $hasQuery = false; Chris@0: if (isset($_SERVER['REQUEST_URI'])) { Chris@17: $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2); Chris@0: $uri = $uri->withPath($requestUriParts[0]); Chris@0: if (isset($requestUriParts[1])) { Chris@0: $hasQuery = true; Chris@0: $uri = $uri->withQuery($requestUriParts[1]); Chris@0: } Chris@0: } Chris@0: Chris@0: if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) { Chris@0: $uri = $uri->withQuery($_SERVER['QUERY_STRING']); Chris@0: } Chris@0: Chris@0: return $uri; Chris@0: } Chris@0: Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getServerParams() Chris@0: { Chris@0: return $this->serverParams; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getUploadedFiles() Chris@0: { Chris@0: return $this->uploadedFiles; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function withUploadedFiles(array $uploadedFiles) Chris@0: { Chris@0: $new = clone $this; Chris@0: $new->uploadedFiles = $uploadedFiles; Chris@0: Chris@0: return $new; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getCookieParams() Chris@0: { Chris@0: return $this->cookieParams; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function withCookieParams(array $cookies) Chris@0: { Chris@0: $new = clone $this; Chris@0: $new->cookieParams = $cookies; Chris@0: Chris@0: return $new; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getQueryParams() Chris@0: { Chris@0: return $this->queryParams; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function withQueryParams(array $query) Chris@0: { Chris@0: $new = clone $this; Chris@0: $new->queryParams = $query; Chris@0: Chris@0: return $new; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getParsedBody() Chris@0: { Chris@0: return $this->parsedBody; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function withParsedBody($data) Chris@0: { Chris@0: $new = clone $this; Chris@0: $new->parsedBody = $data; Chris@0: Chris@0: return $new; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getAttributes() Chris@0: { Chris@0: return $this->attributes; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getAttribute($attribute, $default = null) Chris@0: { Chris@0: if (false === array_key_exists($attribute, $this->attributes)) { Chris@0: return $default; Chris@0: } Chris@0: Chris@0: return $this->attributes[$attribute]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function withAttribute($attribute, $value) Chris@0: { Chris@0: $new = clone $this; Chris@0: $new->attributes[$attribute] = $value; Chris@0: Chris@0: return $new; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function withoutAttribute($attribute) Chris@0: { Chris@0: if (false === array_key_exists($attribute, $this->attributes)) { Chris@0: return $this; Chris@0: } Chris@0: Chris@0: $new = clone $this; Chris@0: unset($new->attributes[$attribute]); Chris@0: Chris@0: return $new; Chris@0: } Chris@0: }