designcise/bitframe

View on GitHub
src/Http/Parser/UriParser.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php

/**
 * BitFrame Framework (https://www.bitframephp.com)
 *
 * @author    Daniyal Hamid
 * @copyright Copyright (c) 2017-2023 Daniyal Hamid (https://designcise.com)
 * @license   https://bitframephp.com/about/license MIT License
 */

declare(strict_types=1);

namespace BitFrame\Http\Parser;

use function rtrim;
use function parse_url;

use const PHP_URL_PORT;

/**
 * Builds a server request.
 */
class UriParser
{
    public static function parse(array $server): array
    {
        $uriParts = parse_url($server['REQUEST_URI'] ?? '');
        [$path, $query, $fragment] = self::extractComponents($server, $uriParts);

        $baseUri = self::createAuthorityWithScheme($server);

        if ($path) {
            $baseUri = rtrim($baseUri, '/') . '/' . ltrim($path, '/');
        }

        $uri = (
            ($baseUri ?: '/')
            . ($query ? ('?' . ltrim($query, '?')) : '')
            . ($fragment ? "#$fragment" : '')
        );

        parse_str($query, $queryParams);

        return [$uri, $queryParams];
    }

    private static function createAuthorityWithScheme(array $server): string
    {
        $authority = $server['HTTP_HOST'] ?? $server['SERVER_NAME'] ?? $server['SERVER_ADDR'] ?? '';

        if ($authority) {
            $scheme = (
                    $server['REQUEST_SCHEME']
                    ?? ('http' . ((isset($server['HTTPS']) && $server['HTTPS'] === 'on') ? 's' : ''))
                ) . ':';

            // @see https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1
            $authority = strtolower("$scheme//$authority");
        }

        if (
            ! $authority
            || ! isset($server['SERVER_PORT'])
            || parse_url($authority, PHP_URL_PORT)
        ) {
            return $authority;
        }

        $port = (empty($server['SERVER_PORT'])) ? '' : ":{$server['SERVER_PORT']}";

        return (
        (str_ends_with($authority, '/'))
            ? rtrim($authority, '/') . "$port/"
            : "$authority$port"
        );
    }

    private static function extractComponents(array $server, array $uriParts): array
    {
        $path = '';

        if (! empty($server['PATH_INFO'])) {
            $path = $server['PATH_INFO'];
        } elseif (! empty($server['ORIG_PATH_INFO'])) {
            $path = $server['ORIG_PATH_INFO'];
        } elseif (! empty($uriParts['path'])) {
            $path = $uriParts['path'];
        }

        $query = '';

        if (! empty($server['QUERY_STRING'])) {
            $query = $server['QUERY_STRING'];
        } elseif (! empty($uriParts['query'])) {
            $query = $uriParts['query'];
        }

        $fragment = (! empty($uriParts['fragment'])) ? $uriParts['fragment'] : '';
        return [$path, $query, $fragment];
    }
}