Размер файла: 8.51Kb
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Psr7;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UploadedFileInterface;
use Psr\Http\Message\UriInterface;
use Slim\Psr7\Interfaces\HeadersInterface;
use function get_class;
use function gettype;
use function is_array;
use function is_null;
use function is_object;
use function is_string;
use function ltrim;
use function parse_str;
use function preg_match;
use function sprintf;
use function str_replace;
class Request extends Message implements ServerRequestInterface
{
/**
* @var string
*/
protected $method;
/**
* @var UriInterface
*/
protected $uri;
/**
* @var string
*/
protected $requestTarget;
/**
* @var ?array
*/
protected $queryParams;
protected array $cookies;
protected array $serverParams;
protected array $attributes;
/**
* @var null|array|object
*/
protected $parsedBody;
/**
* @var UploadedFileInterface[]
*/
protected array $uploadedFiles;
/**
* @param string $method The request method
* @param UriInterface $uri The request URI object
* @param HeadersInterface $headers The request headers collection
* @param array $cookies The request cookies collection
* @param array $serverParams The server environment variables
* @param StreamInterface $body The request body object
* @param array $uploadedFiles The request uploadedFiles collection
* @throws InvalidArgumentException on invalid HTTP method
*/
public function __construct(
$method,
UriInterface $uri,
HeadersInterface $headers,
array $cookies,
array $serverParams,
StreamInterface $body,
array $uploadedFiles = []
) {
$this->method = $this->filterMethod($method);
$this->uri = $uri;
$this->headers = $headers;
$this->cookies = $cookies;
$this->serverParams = $serverParams;
$this->attributes = [];
$this->body = $body;
$this->uploadedFiles = $uploadedFiles;
if (isset($serverParams['SERVER_PROTOCOL'])) {
$this->protocolVersion = str_replace('HTTP/', '', $serverParams['SERVER_PROTOCOL']);
}
if (!$this->headers->hasHeader('Host') || $this->uri->getHost() !== '') {
$this->headers->setHeader('Host', $this->uri->getHost());
}
}
/**
* This method is applied to the cloned object after PHP performs an initial shallow-copy.
* This method completes a deep-copy by creating new objects for the cloned object's internal reference pointers.
*/
public function __clone()
{
$this->headers = clone $this->headers;
$this->body = clone $this->body;
}
/**
* {@inheritdoc}
*/
public function getMethod(): string
{
return $this->method;
}
/**
* {@inheritdoc}
* @return static
*/
public function withMethod($method)
{
$method = $this->filterMethod($method);
$clone = clone $this;
$clone->method = $method;
return $clone;
}
/**
* Validate the HTTP method
*
* @param string $method
*
* @return string
*
* @throws InvalidArgumentException on invalid HTTP method.
*/
protected function filterMethod($method): string
{
/** @var mixed $method */
if (!is_string($method)) {
throw new InvalidArgumentException(sprintf(
'Unsupported HTTP method; must be a string, received %s',
(is_object($method) ? get_class($method) : gettype($method))
));
}
if (preg_match("/^[!#$%&'*+.^_`|~0-9a-z-]+$/i", $method) !== 1) {
throw new InvalidArgumentException(sprintf(
'Unsupported HTTP method "%s" provided',
$method
));
}
return $method;
}
/**
* {@inheritdoc}
*/
public function getRequestTarget(): string
{
if ($this->requestTarget) {
return $this->requestTarget;
}
if ($this->uri === null) {
return '/';
}
$path = $this->uri->getPath();
$path = '/' . ltrim($path, '/');
$query = $this->uri->getQuery();
if ($query) {
$path .= '?' . $query;
}
return $path;
}
/**
* {@inheritdoc}
* @return static
*/
public function withRequestTarget($requestTarget)
{
if (!is_string($requestTarget) || preg_match('#\s#', $requestTarget)) {
throw new InvalidArgumentException(
'Invalid request target provided; must be a string and cannot contain whitespace'
);
}
$clone = clone $this;
$clone->requestTarget = $requestTarget;
return $clone;
}
/**
* {@inheritdoc}
*/
public function getUri(): UriInterface
{
return $this->uri;
}
/**
* {@inheritdoc}
* @return static
*/
public function withUri(UriInterface $uri, $preserveHost = false)
{
$clone = clone $this;
$clone->uri = $uri;
if (!$preserveHost && $uri->getHost() !== '') {
$clone->headers->setHeader('Host', $uri->getHost());
return $clone;
}
if (($uri->getHost() !== '' && !$this->hasHeader('Host') || $this->getHeaderLine('Host') === '')) {
$clone->headers->setHeader('Host', $uri->getHost());
return $clone;
}
return $clone;
}
/**
* {@inheritdoc}
*/
public function getCookieParams(): array
{
return $this->cookies;
}
/**
* {@inheritdoc}
* @return static
*/
public function withCookieParams(array $cookies)
{
$clone = clone $this;
$clone->cookies = $cookies;
return $clone;
}
/**
* {@inheritdoc}
*/
public function getQueryParams(): array
{
if (is_array($this->queryParams)) {
return $this->queryParams;
}
if ($this->uri === null) {
return [];
}
parse_str($this->uri->getQuery(), $this->queryParams); // <-- URL decodes data
assert(is_array($this->queryParams));
return $this->queryParams;
}
/**
* {@inheritdoc}
* @return static
*/
public function withQueryParams(array $query)
{
$clone = clone $this;
$clone->queryParams = $query;
return $clone;
}
/**
* {@inheritdoc}
*/
public function getUploadedFiles(): array
{
return $this->uploadedFiles;
}
/**
* {@inheritdoc}
* @return static
*/
public function withUploadedFiles(array $uploadedFiles)
{
$clone = clone $this;
$clone->uploadedFiles = $uploadedFiles;
return $clone;
}
/**
* {@inheritdoc}
*/
public function getServerParams(): array
{
return $this->serverParams;
}
/**
* {@inheritdoc}
*/
public function getAttributes(): array
{
return $this->attributes;
}
/**
* {@inheritdoc}
* @return mixed
*/
public function getAttribute($name, $default = null)
{
return $this->attributes[$name] ?? $default;
}
/**
* {@inheritdoc}
* @return static
*/
public function withAttribute($name, $value)
{
$clone = clone $this;
$clone->attributes[$name] = $value;
return $clone;
}
/**
* {@inheritdoc}
* @return static
*/
public function withoutAttribute($name)
{
$clone = clone $this;
unset($clone->attributes[$name]);
return $clone;
}
/**
* {@inheritdoc}
*/
public function getParsedBody()
{
return $this->parsedBody;
}
/**
* {@inheritdoc}
* @return static
*/
public function withParsedBody($data)
{
/** @var mixed $data */
if (!is_null($data) && !is_object($data) && !is_array($data)) {
throw new InvalidArgumentException('Parsed body value must be an array, an object, or null');
}
$clone = clone $this;
$clone->parsedBody = $data;
return $clone;
}
}