PHP Classes
elePHPant
Icontem

File: _functions.php

Recommend this page to a friend!
  Classes of Payam Naderi  >  PSR-7  >  _functions.php  >  Download  
File: _functions.php
Role: Auxiliary script
Content type: text/plain
Description: Auxiliary script
Class: PSR-7
Implements PSR-7 HTTP message interfaces
Author: By
Last change: code cleanup
Merge remote-tracking branch 'origin/master'
Date: 9 months ago
Size: 12,275 bytes
 

Contents

Class file image Download
<?php
namespace Poirot\Psr7\Response
{
    // TODO Code clone from Poirot\Http\Response 

    /**
     * Map of standard HTTP status code/reason phrases
     *
     * @var array
     */
    $phrases = array(
        // INFORMATIONAL CODES
        100 => 'Continue',
        101 => 'Switching Protocols',
        102 => 'Processing',
        // SUCCESS CODES
        200 => 'OK',
        201 => 'Created',
        202 => 'Accepted',
        203 => 'Non-Authoritative Information',
        204 => 'No Content',
        205 => 'Reset Content',
        206 => 'Partial Content',
        207 => 'Multi-status',
        208 => 'Already Reported',
        // REDIRECTION CODES
        300 => 'Multiple Choices',
        301 => 'Moved Permanently',
        302 => 'Found',
        303 => 'See Other',
        304 => 'Not Modified',
        305 => 'Use Proxy',
        306 => 'Switch Proxy', // Deprecated
        307 => 'Temporary Redirect',
        // CLIENT ERROR
        400 => 'Bad Request',
        401 => 'Unauthorized',
        402 => 'Payment Required',
        403 => 'Forbidden',
        404 => 'Not Found',
        405 => 'Method Not Allowed',
        406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required',
        408 => 'Request Time-out',
        409 => 'Conflict',
        410 => 'Gone',
        411 => 'Length Required',
        412 => 'Precondition Failed',
        413 => 'Request Entity Too Large',
        414 => 'Request-URI Too Large',
        415 => 'Unsupported Media Type',
        416 => 'Requested range not satisfiable',
        417 => 'Expectation Failed',
        418 => 'I\'m a teapot',
        422 => 'Unprocessable Entity',
        423 => 'Locked',
        424 => 'Failed Dependency',
        425 => 'Unordered Collection',
        426 => 'Upgrade Required',
        428 => 'Precondition Required',
        429 => 'Too Many Requests',
        431 => 'Request Header Fields Too Large',
        // SERVER ERROR
        500 => 'Internal Server Error',
        501 => 'Not Implemented',
        502 => 'Bad Gateway',
        503 => 'Service Unavailable',
        504 => 'Gateway Time-out',
        505 => 'HTTP Version not supported',
        506 => 'Variant Also Negotiates',
        507 => 'Insufficient Storage',
        508 => 'Loop Detected',
        511 => 'Network Authentication Required',
    );
    /**
     * Get Status Code Reason
     *
     * @param int $statusCode
     *
     * @return null|string
     */
    function getStatReasonFromCode($statusCode)
    {
        global $phrases;
        return isset($phrases[$statusCode]) ? $phrases[$statusCode] : null;
    }
}

namespace Poirot\Psr7
{

    use Poirot\Ioc\instance;
    use Poirot\Std\Type\StdTravers;
    use Psr\Http\Message\MessageInterface;
    use Psr\Http\Message\RequestInterface;
    use Psr\Http\Message\ResponseInterface;
    use Psr\Http\Message\UriInterface;
    
    const URI_APPEND  = 'uri.path.append';
    const URI_PREPEND = 'uri.path.prepend';


    /**
     * String representation of an HTTP message.
     *
     * @param MessageInterface $httpMessage
     *
     * @return string
     */
    function renderHttpMessage(MessageInterface $httpMessage)
    {
        $msg = renderHeaderHttpMessage($httpMessage);
        return "{$msg}\r\n" . $httpMessage->getBody();
    }

    /**
     * String representation of Headers of an HTTP message.
     *
     * @param MessageInterface $httpMessage
     *
     * @return string
     */
    function renderHeaderHttpMessage(MessageInterface $httpMessage)
    {
        if ($httpMessage instanceof RequestInterface) {
            $msg = trim($httpMessage->getMethod() . ' '
                    . $httpMessage->getRequestTarget())
                . ' HTTP/' . $httpMessage->getProtocolVersion();
            if (!$httpMessage->hasHeader('host'))
                $msg .= "\r\nHost: " . $httpMessage->getUri()->getHost();
        } elseif ($httpMessage instanceof ResponseInterface) {
            $msg = 'HTTP/' . $httpMessage->getProtocolVersion() . ' '
                . $httpMessage->getStatusCode() . ' '
                . $httpMessage->getReasonPhrase();
        } else
            throw new \InvalidArgumentException('Unknown message type');

        foreach ($httpMessage->getHeaders() as $name => $values) {
            $msg .= "\r\n{$name}: ".$httpMessage->getHeaderLine($name);
        }

        return "{$msg}\r\n";
    }
    
    /**
     * Clone and modify a uri with the given changes.
     *
     * - current values Must merge with given changes
     *
     * @param UriInterface       $uri
     * @param array|\Traversable $changes
     * @param string             $uriPath
     *
     * @return UriInterface
     */
    function modifyUri(UriInterface $uri, $changes, $uriPath = URI_PREPEND)
    {
        if ($changes instanceof \Traversable)
            $changes = \Poirot\Std\cast($changes)->toArray();
        
        if (!is_array($changes))
            throw new \InvalidArgumentException(sprintf(
                'Changes must be an array or instance of Traversable; given: (%s).'
                , \Poirot\Std\flatten($changes)
            ));
        
        
        $uri = clone $uri;
        if (isset($changes['scheme']))
            $uri = $uri->withScheme($changes['scheme']);
        if (isset($changes['host']))
            $uri = $uri->withHost($changes['host']);
        if (isset($changes['port']))
            $uri = $uri->withPort($changes['port']);
        if (isset($changes['user_info'])) {
            if (empty($changes['user_info']))
                // remove user info
                $uri = $uri->withUserInfo('');
            else {
                list ($username, $password) = explode(':', $changes['user_info']);
                $uri = $uri->withUserInfo($username, $password);
            }
        }
        if (isset($changes['fragment']))
            $uri = $uri->withFragment($changes['fragment']);

        if (isset($changes['path'])) {
            $curPath = $uri->getPath();
            if ($uriPath === URI_PREPEND)
                $uri = $uri->withPath(rtrim($changes['path'], '/').'/'.trim($curPath,'/'));
            else
                $uri = $uri->withPath(rtrim($curPath, '/').'/'.trim($changes['path'], '/'));
        }

        if (isset($changes['query'])) {
            $query = $changes['query'];
            if (is_string($query))
                $mrgQuery = parseQuery($changes['query']);
            elseif ($query instanceof \Traversable)
                $mrgQuery = StdTravers::of($query)->toArray();
            else
                $mrgQuery = $query;

            if (!is_array($mrgQuery))
                throw new \InvalidArgumentException(sprintf(
                    'Query params must be Traversable or array or query string. given: (%s).'
                    , \Poirot\Std\flatten($mrgQuery)
                ));

            $curQuery = parseQuery($uri->getQuery());

            if ($uriPath === URI_PREPEND)
                $query = array_merge($curQuery, $mrgQuery);
            else
                $query = array_merge($mrgQuery, $curQuery);

            foreach ($query as $key => $val) {
                // Cleanup null values from query params
                if ($val === null)
                    unset($query[$key]);
            }

            $uri = $uri->withQuery(buildQuery($query));
        }

        return $uri;
    }

    /**
     * Parse Psr Uri To It's Parts
     *
     * @param UriInterface $uri
     *
     * @return array
     */
    function parseUriPsr(UriInterface $uri)
    {
        $parsed = array(
            'scheme'    => $uri->getScheme(),
            'user_info' => $uri->getUserInfo(),
            'host'      => $uri->getHost(),
            'port'      => $uri->getPort(),
            'path'      => $uri->getPath(),
            'query'     => $uri->getQuery(),
            'fragment'  => $uri->getFragment(),
        );
        
        return $parsed;
    }
    
    /**
     * Build a query string from an array of key value pairs.
     *
     * This function can use the return value of parseQuery() to build a query
     * string. This function does not modify the provided keys when an array is
     * encountered (like http_build_query would).
     *
     * @param array     $params   Query string parameters.
     * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986
     *                            to encode using RFC3986, or PHP_QUERY_RFC1738
     *                            to encode using RFC1738.
     * @return string
     */
    function buildQuery(array $params, $encoding = PHP_QUERY_RFC3986)
    {
        if (!$params)
            return '';

        if ($encoding === false) {
            $encoder = function ($str) { return $str; };
        } elseif ($encoding == PHP_QUERY_RFC3986) {
            $encoder = 'rawurlencode';
        } elseif ($encoding == PHP_QUERY_RFC1738) {
            $encoder = 'urlencode';
        } else {
            throw new \InvalidArgumentException('Invalid type');
        }

        $qs = '';
        foreach ($params as $k => $v) {
            if ($v === null)
                // null meaning not has value; so delete it
                continue;

            $k = $encoder($k);
            if (!is_array($v)) {
                $qs .= $k;
                if ($v !== null) {
                    $qs .= '=' . $encoder($v);
                }
                $qs .= '&';
            } else {
                foreach ($v as $vv) {
                    $qs .= $k;
                    if ($vv !== null) {
                        $qs .= '=' . $encoder($vv);
                    }
                    $qs .= '&';
                }
            }
        }

        return $qs ? (string) substr($qs, 0, -1) : '';
    }

    /**
     * Parse a query string into an associative array.
     *
     * If multiple values are found for the same key, the value of that key
     * value pair will become an array. This function does not parse nested
     * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
     * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
     *
     * @param string      $str         Query string to parse
     * @param bool|string $urlEncoding How the query string is encoded
     *
     * @return array
     */
    function parseQuery($str, $urlEncoding = true)
    {
        $result = array();
        $str    = (string) $str;

        if ($str === '') {
            return $result;
        }

        if ($urlEncoding === true) {
            $decoder = function ($value) {
                return rawurldecode(str_replace('+', ' ', $value));
            };
        } elseif ($urlEncoding == PHP_QUERY_RFC3986) {
            $decoder = 'rawurldecode';
        } elseif ($urlEncoding == PHP_QUERY_RFC1738) {
            $decoder = 'urldecode';
        } else {
            $decoder = function ($str) { return $str; };
        }

        foreach (explode('&', $str) as $kvp) {
            $parts = explode('=', $kvp, 2);
            $key = $decoder($parts[0]);
            $value = isset($parts[1]) ? $decoder($parts[1]) : null;
            if (!isset($result[$key])) {
                $result[$key] = $value;
            } else {
                if (!is_array($result[$key])) {
                    $result[$key] = array($result[$key]);
                }
                $result[$key][] = $value;
            }
        }

        return $result;
    }

    function getUploadErrorMessageFromCode($code)
    {
        switch ($code) {
            case UPLOAD_ERR_INI_SIZE:
                $message = 'The uploaded file exceeds the Server filesize Setting.';
                break;
            case UPLOAD_ERR_FORM_SIZE:
                $message = 'The uploaded file exceeds the Form filesize Setting.';
                break;
            case UPLOAD_ERR_NO_FILE:
                $message = 'No file was uploaded.';
                break;
            case UPLOAD_ERR_NO_TMP_DIR:
                $message = 'Missing a temporary folder.';
                break;
            case UPLOAD_ERR_CANT_WRITE:
                $message = 'Failed to write file to disk.';
                break;

            default: $message = $code;
        }

        return $message;
    }
}