2015-08-27 12:03:05 -07:00
< ? php
/**
2018-11-23 12:29:20 +00:00
* @ see https :// github . com / zendframework / zend - diactoros for the canonical source repository
* @ copyright Copyright ( c ) 2015 - 2017 Zend Technologies USA Inc . ( http :// www . zend . com )
2015-08-27 12:03:05 -07:00
* @ license https :// github . com / zendframework / zend - diactoros / blob / master / LICENSE . md New BSD License
*/
namespace Zend\Diactoros ;
use InvalidArgumentException ;
use Psr\Http\Message\ServerRequestInterface ;
use Psr\Http\Message\StreamInterface ;
use Psr\Http\Message\UploadedFileInterface ;
2017-04-13 15:53:35 +01:00
use Psr\Http\Message\UriInterface ;
2015-08-27 12:03:05 -07:00
2018-11-23 12:29:20 +00:00
use function array_key_exists ;
use function is_array ;
2015-08-27 12:03:05 -07:00
/**
* Server - side HTTP request
*
* Extends the Request definition to add methods for accessing incoming data ,
* specifically server parameters , cookies , matched path parameters , query
* string arguments , body parameters , and upload file information .
*
* " Attributes " are discovered via decomposing the request ( and usually
* specifically the URI path ), and typically will be injected by the application .
*
* Requests are considered immutable ; all methods that might change state are
* implemented such that they retain the internal state of the current
* message and return a new instance that contains the changed state .
*/
class ServerRequest implements ServerRequestInterface
{
2017-04-13 15:53:35 +01:00
use RequestTrait ;
2015-08-27 12:03:05 -07:00
/**
* @ var array
*/
private $attributes = [];
/**
* @ var array
*/
private $cookieParams = [];
/**
* @ var null | array | object
*/
private $parsedBody ;
/**
* @ var array
*/
private $queryParams = [];
/**
* @ var array
*/
private $serverParams ;
/**
* @ var array
*/
private $uploadedFiles ;
/**
* @ param array $serverParams Server parameters , typically from $_SERVER
* @ param array $uploadedFiles Upload file information , a tree of UploadedFiles
2017-04-13 15:53:35 +01:00
* @ param null | string | UriInterface $uri URI for the request , if any .
2015-08-27 12:03:05 -07:00
* @ param null | string $method HTTP method for the request , if any .
* @ param string | resource | StreamInterface $body Message body , if any .
* @ param array $headers Headers for the message , if any .
2017-04-13 15:53:35 +01:00
* @ param array $cookies Cookies for the message , if any .
* @ param array $queryParams Query params for the message , if any .
* @ param null | array | object $parsedBody The deserialized body parameters , if any .
* @ param string $protocol HTTP protocol version .
2015-08-27 12:03:05 -07:00
* @ throws InvalidArgumentException for any invalid value .
*/
public function __construct (
array $serverParams = [],
array $uploadedFiles = [],
$uri = null ,
$method = null ,
$body = 'php://input' ,
2017-04-13 15:53:35 +01:00
array $headers = [],
array $cookies = [],
array $queryParams = [],
$parsedBody = null ,
$protocol = '1.1'
2015-08-27 12:03:05 -07:00
) {
$this -> validateUploadedFiles ( $uploadedFiles );
2017-04-13 15:53:35 +01:00
if ( $body === 'php://input' ) {
$body = new PhpInputStream ();
}
2015-08-27 12:03:05 -07:00
$this -> initialize ( $uri , $method , $body , $headers );
$this -> serverParams = $serverParams ;
$this -> uploadedFiles = $uploadedFiles ;
2017-04-13 15:53:35 +01:00
$this -> cookieParams = $cookies ;
$this -> queryParams = $queryParams ;
$this -> parsedBody = $parsedBody ;
$this -> protocol = $protocol ;
2015-08-27 12:03:05 -07:00
}
/**
* { @ inheritdoc }
*/
public function getServerParams ()
{
return $this -> serverParams ;
}
/**
* { @ inheritdoc }
*/
public function getUploadedFiles ()
{
return $this -> uploadedFiles ;
}
/**
* { @ inheritdoc }
*/
public function withUploadedFiles ( array $uploadedFiles )
{
$this -> validateUploadedFiles ( $uploadedFiles );
$new = clone $this ;
$new -> uploadedFiles = $uploadedFiles ;
return $new ;
}
/**
* { @ inheritdoc }
*/
public function getCookieParams ()
{
return $this -> cookieParams ;
}
/**
* { @ inheritdoc }
*/
public function withCookieParams ( array $cookies )
{
$new = clone $this ;
$new -> cookieParams = $cookies ;
return $new ;
}
/**
* { @ inheritdoc }
*/
public function getQueryParams ()
{
return $this -> queryParams ;
}
/**
* { @ inheritdoc }
*/
public function withQueryParams ( array $query )
{
$new = clone $this ;
$new -> queryParams = $query ;
return $new ;
}
/**
* { @ inheritdoc }
*/
public function getParsedBody ()
{
return $this -> parsedBody ;
}
/**
* { @ inheritdoc }
*/
public function withParsedBody ( $data )
{
2018-11-23 12:29:20 +00:00
if ( ! is_array ( $data ) && ! is_object ( $data ) && null !== $data ) {
throw new InvalidArgumentException ( sprintf (
'%s expects a null, array, or object argument; received %s' ,
__METHOD__ ,
gettype ( $data )
));
}
2015-08-27 12:03:05 -07:00
$new = clone $this ;
$new -> parsedBody = $data ;
return $new ;
}
/**
* { @ inheritdoc }
*/
public function getAttributes ()
{
return $this -> attributes ;
}
/**
* { @ inheritdoc }
*/
public function getAttribute ( $attribute , $default = null )
{
if ( ! array_key_exists ( $attribute , $this -> attributes )) {
return $default ;
}
return $this -> attributes [ $attribute ];
}
/**
* { @ inheritdoc }
*/
public function withAttribute ( $attribute , $value )
{
$new = clone $this ;
$new -> attributes [ $attribute ] = $value ;
return $new ;
}
/**
* { @ inheritdoc }
*/
public function withoutAttribute ( $attribute )
{
$new = clone $this ;
unset ( $new -> attributes [ $attribute ]);
return $new ;
}
/**
* Proxy to receive the request method .
*
* This overrides the parent functionality to ensure the method is never
* empty ; if no method is present , it returns 'GET' .
*
* @ return string
*/
public function getMethod ()
{
if ( empty ( $this -> method )) {
return 'GET' ;
}
return $this -> method ;
}
/**
* Set the request method .
*
* Unlike the regular Request implementation , the server - side
* normalizes the method to uppercase to ensure consistency
* and make checking the method simpler .
*
* This methods returns a new instance .
*
* @ param string $method
* @ return self
*/
public function withMethod ( $method )
{
$this -> validateMethod ( $method );
$new = clone $this ;
$new -> method = $method ;
return $new ;
}
/**
* Recursively validate the structure in an uploaded files array .
*
* @ param array $uploadedFiles
* @ throws InvalidArgumentException if any leaf is not an UploadedFileInterface instance .
*/
private function validateUploadedFiles ( array $uploadedFiles )
{
foreach ( $uploadedFiles as $file ) {
if ( is_array ( $file )) {
$this -> validateUploadedFiles ( $file );
continue ;
}
if ( ! $file instanceof UploadedFileInterface ) {
throw new InvalidArgumentException ( 'Invalid leaf in uploaded files structure' );
}
}
}
}