347 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			347 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace GuzzleHttp\Psr7;
 | 
						|
 | 
						|
use InvalidArgumentException;
 | 
						|
use Psr\Http\Message\ServerRequestInterface;
 | 
						|
use Psr\Http\Message\UriInterface;
 | 
						|
use Psr\Http\Message\StreamInterface;
 | 
						|
use Psr\Http\Message\UploadedFileInterface;
 | 
						|
 | 
						|
/**
 | 
						|
 * 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 extends Request implements ServerRequestInterface
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * @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 string                               $method       HTTP method
 | 
						|
     * @param string|UriInterface                  $uri          URI
 | 
						|
     * @param array                                $headers      Request headers
 | 
						|
     * @param string|null|resource|StreamInterface $body         Request body
 | 
						|
     * @param string                               $version      Protocol version
 | 
						|
     * @param array                                $serverParams Typically the $_SERVER superglobal
 | 
						|
     */
 | 
						|
    public function __construct(
 | 
						|
        $method,
 | 
						|
        $uri,
 | 
						|
        array $headers = [],
 | 
						|
        $body = null,
 | 
						|
        $version = '1.1',
 | 
						|
        array $serverParams = []
 | 
						|
    ) {
 | 
						|
        $this->serverParams = $serverParams;
 | 
						|
 | 
						|
        parent::__construct($method, $uri, $headers, $body, $version);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Return an UploadedFile instance array.
 | 
						|
     *
 | 
						|
     * @param array $files A array which respect $_FILES structure
 | 
						|
     * @throws InvalidArgumentException for unrecognized values
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public static function normalizeFiles(array $files)
 | 
						|
    {
 | 
						|
        $normalized = [];
 | 
						|
 | 
						|
        foreach ($files as $key => $value) {
 | 
						|
            if ($value instanceof UploadedFileInterface) {
 | 
						|
                $normalized[$key] = $value;
 | 
						|
            } elseif (is_array($value) && isset($value['tmp_name'])) {
 | 
						|
                $normalized[$key] = self::createUploadedFileFromSpec($value);
 | 
						|
            } elseif (is_array($value)) {
 | 
						|
                $normalized[$key] = self::normalizeFiles($value);
 | 
						|
                continue;
 | 
						|
            } else {
 | 
						|
                throw new InvalidArgumentException('Invalid value in files specification');
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return $normalized;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Create and return an UploadedFile instance from a $_FILES specification.
 | 
						|
     *
 | 
						|
     * If the specification represents an array of values, this method will
 | 
						|
     * delegate to normalizeNestedFileSpec() and return that return value.
 | 
						|
     *
 | 
						|
     * @param array $value $_FILES struct
 | 
						|
     * @return array|UploadedFileInterface
 | 
						|
     */
 | 
						|
    private static function createUploadedFileFromSpec(array $value)
 | 
						|
    {
 | 
						|
        if (is_array($value['tmp_name'])) {
 | 
						|
            return self::normalizeNestedFileSpec($value);
 | 
						|
        }
 | 
						|
 | 
						|
        return new UploadedFile(
 | 
						|
            $value['tmp_name'],
 | 
						|
            (int) $value['size'],
 | 
						|
            (int) $value['error'],
 | 
						|
            $value['name'],
 | 
						|
            $value['type']
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Normalize an array of file specifications.
 | 
						|
     *
 | 
						|
     * Loops through all nested files and returns a normalized array of
 | 
						|
     * UploadedFileInterface instances.
 | 
						|
     *
 | 
						|
     * @param array $files
 | 
						|
     * @return UploadedFileInterface[]
 | 
						|
     */
 | 
						|
    private static function normalizeNestedFileSpec(array $files = [])
 | 
						|
    {
 | 
						|
        $normalizedFiles = [];
 | 
						|
 | 
						|
        foreach (array_keys($files['tmp_name']) as $key) {
 | 
						|
            $spec = [
 | 
						|
                'tmp_name' => $files['tmp_name'][$key],
 | 
						|
                'size'     => $files['size'][$key],
 | 
						|
                'error'    => $files['error'][$key],
 | 
						|
                'name'     => $files['name'][$key],
 | 
						|
                'type'     => $files['type'][$key],
 | 
						|
            ];
 | 
						|
            $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
 | 
						|
        }
 | 
						|
 | 
						|
        return $normalizedFiles;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Return a ServerRequest populated with superglobals:
 | 
						|
     * $_GET
 | 
						|
     * $_POST
 | 
						|
     * $_COOKIE
 | 
						|
     * $_FILES
 | 
						|
     * $_SERVER
 | 
						|
     *
 | 
						|
     * @return ServerRequestInterface
 | 
						|
     */
 | 
						|
    public static function fromGlobals()
 | 
						|
    {
 | 
						|
        $method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : 'GET';
 | 
						|
        $headers = function_exists('getallheaders') ? getallheaders() : [];
 | 
						|
        $uri = self::getUriFromGlobals();
 | 
						|
        $body = new LazyOpenStream('php://input', 'r+');
 | 
						|
        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', sanitize_text_field( wp_unslash( $_SERVER['SERVER_PROTOCOL'] ) ) ) : '1.1';
 | 
						|
 | 
						|
        $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
 | 
						|
 | 
						|
        return $serverRequest
 | 
						|
            ->withCookieParams($_COOKIE)
 | 
						|
            ->withQueryParams($_GET)
 | 
						|
            ->withParsedBody($_POST)
 | 
						|
            ->withUploadedFiles(self::normalizeFiles($_FILES));
 | 
						|
    }
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get a Uri populated with values from $_SERVER.
 | 
						|
	 *
 | 
						|
	 * @return UriInterface
 | 
						|
	 */
 | 
						|
	public static function getUriFromGlobals() {
 | 
						|
		$uri = new Uri( '' );
 | 
						|
 | 
						|
		if ( isset( $_SERVER['HTTPS'] ) ) {
 | 
						|
			$uri = $uri->withScheme( sanitize_text_field( wp_unslash( $_SERVER['HTTPS'] ) ) == 'on' ? 'https' : 'http');
 | 
						|
		}
 | 
						|
 | 
						|
		if ( isset( $_SERVER['HTTP_HOST'] ) ) {
 | 
						|
			$uri = $uri->withHost( sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) );
 | 
						|
		} elseif ( isset( $_SERVER['SERVER_NAME'] ) ) {
 | 
						|
			$uri = $uri->withHost( sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ) );
 | 
						|
		}
 | 
						|
 | 
						|
		if ( isset( $_SERVER['SERVER_PORT'] ) ) {
 | 
						|
			$uri = $uri->withPort( sanitize_text_field( wp_unslash( $_SERVER['SERVER_PORT'] ) ) );
 | 
						|
		}
 | 
						|
 | 
						|
		if ( isset( $_SERVER['REQUEST_URI'] ) ) {
 | 
						|
			$uri = $uri->withPath( current( explode( '?', sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ) );
 | 
						|
		}
 | 
						|
 | 
						|
		if ( isset( $_SERVER['QUERY_STRING'] ) ) {
 | 
						|
			$uri = $uri->withQuery( sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ) );
 | 
						|
		}
 | 
						|
 | 
						|
		return $uri;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
    /**
 | 
						|
     * {@inheritdoc}
 | 
						|
     */
 | 
						|
    public function getServerParams()
 | 
						|
    {
 | 
						|
        return $this->serverParams;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * {@inheritdoc}
 | 
						|
     */
 | 
						|
    public function getUploadedFiles()
 | 
						|
    {
 | 
						|
        return $this->uploadedFiles;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * {@inheritdoc}
 | 
						|
     */
 | 
						|
    public function withUploadedFiles(array $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)
 | 
						|
    {
 | 
						|
        $new = clone $this;
 | 
						|
        $new->parsedBody = $data;
 | 
						|
 | 
						|
        return $new;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * {@inheritdoc}
 | 
						|
     */
 | 
						|
    public function getAttributes()
 | 
						|
    {
 | 
						|
        return $this->attributes;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * {@inheritdoc}
 | 
						|
     */
 | 
						|
    public function getAttribute($attribute, $default = null)
 | 
						|
    {
 | 
						|
        if (false === 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)
 | 
						|
    {
 | 
						|
        if (false === array_key_exists($attribute, $this->attributes)) {
 | 
						|
            return $this;
 | 
						|
        }
 | 
						|
 | 
						|
        $new = clone $this;
 | 
						|
        unset($new->attributes[$attribute]);
 | 
						|
 | 
						|
        return $new;
 | 
						|
    }
 | 
						|
}
 |