Passed
Pull Request — master (#164)
by ignace nyamagana
03:03
created

UriInfo::emptyComponentValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Uri (https://uri.thephpleague.com)
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace League\Uri;
15
16
use League\Uri\Contracts\UriInterface;
17
use Psr\Http\Message\UriInterface as Psr7UriInterface;
18
use function explode;
19
use function implode;
20
use function preg_replace_callback;
21
use function rawurldecode;
22
use function sprintf;
23
24
final class UriInfo
25
{
26
    private const REGEXP_ENCODED_CHARS = ',%(2[D|E]|3[0-9]|4[1-9|A-F]|5[0-9|A|F]|6[1-9|A-F]|7[0-9|E]),i';
27
28
    private const SCHEME_BLOB = 'blob';
29
30
    private const SCHEME_FILE = 'file';
31
32
    /**
33
     * @codeCoverageIgnore
34
     */
35
    private function __construct()
36
    {
37
    }
38
39
    /**
40
     * @param Psr7UriInterface|UriInterface $uri
41
     */
42 142
    private static function emptyComponentValue($uri): ?string
43
    {
44 142
        return $uri instanceof Psr7UriInterface ? '' : null;
45
    }
46
47
    /**
48
     * Filter the URI object.
49
     *
50
     * To be valid an URI MUST implement at least one of the following interface:
51
     *     - League\Uri\UriInterface
52
     *     - Psr\Http\Message\UriInterface
53
     *
54
     * @param mixed $uri the URI to validate
55
     *
56
     * @throws \TypeError if the URI object does not implements the supported interfaces.
57
     *
58
     * @return Psr7UriInterface|UriInterface
59
     */
60 150
    private static function filterUri($uri)
61
    {
62 150
        if ($uri instanceof Psr7UriInterface || $uri instanceof UriInterface) {
63 140
            return $uri;
64
        }
65
66 12
        throw new \TypeError(sprintf('The uri must be a valid URI object received `%s`', is_object($uri) ? get_class($uri) : gettype($uri)));
67
    }
68
69
    /**
70
     * Normalize an URI for comparison.
71
     *
72
     * @param Psr7UriInterface|UriInterface $uri
73
     *
74
     * @return Psr7UriInterface|UriInterface
75
     */
76 24
    private static function normalize($uri)
77
    {
78 24
        $uri = self::filterUri($uri);
79 22
        $null = self::emptyComponentValue($uri);
80
81 22
        $path = $uri->getPath();
82 22
        if ('/' === ($path[0] ?? '') || '' !== $uri->getScheme().$uri->getAuthority()) {
83 18
            $path = UriResolver::resolve($uri, $uri->withPath('')->withQuery($null))->getPath();
84
        }
85
86 22
        $query = $uri->getQuery();
87 22
        $fragment = $uri->getFragment();
88 22
        $fragmentOrig = $fragment;
89 22
        $pairs = null === $query ? [] : explode('&', $query);
90 22
        sort($pairs, SORT_REGULAR);
91
92
        $replace = static function (array $matches): string {
93 4
            return rawurldecode($matches[0]);
94 22
        };
95
96 22
        $retval = preg_replace_callback(self::REGEXP_ENCODED_CHARS, $replace, [$path, implode('&', $pairs), $fragment]);
97 22
        if (null !== $retval) {
98 22
            [$path, $query, $fragment] = $retval + ['', $null, $null];
99
        }
100
101 22
        if ($null !== $uri->getAuthority() && '' === $path) {
102 10
            $path = '/';
103
        }
104
105
        return $uri
106 22
            ->withHost(Uri::createFromComponents(['host' => $uri->getHost()])->getHost())
107 22
            ->withPath($path)
108 22
            ->withQuery([] === $pairs ? $null : $query)
109 22
            ->withFragment($null === $fragmentOrig ? $fragmentOrig : $fragment);
110
    }
111
112
    /**
113
     * Tell whether the URI represents an absolute URI.
114
     *
115
     * @param Psr7UriInterface|UriInterface $uri
116
     */
117 22
    public static function isAbsolute($uri): bool
118
    {
119 22
        return self::emptyComponentValue($uri) !== self::filterUri($uri)->getScheme();
120
    }
121
122
    /**
123
     * Tell whether the URI represents a network path.
124
     *
125
     * @param Psr7UriInterface|UriInterface $uri
126
     */
127 10
    public static function isNetworkPath($uri): bool
128
    {
129 10
        $uri = self::filterUri($uri);
130 8
        $null = self::emptyComponentValue($uri);
131
132 8
        return $null === $uri->getScheme() && $null !== $uri->getAuthority();
133
    }
134
135
    /**
136
     * Tell whether the URI represents an absolute path.
137
     *
138
     * @param Psr7UriInterface|UriInterface $uri
139
     */
140 10
    public static function isAbsolutePath($uri): bool
141
    {
142 10
        $uri = self::filterUri($uri);
143 8
        $null = self::emptyComponentValue($uri);
144
145 8
        return $null === $uri->getScheme()
146 8
            && $null === $uri->getAuthority()
147 8
            && '/' === ($uri->getPath()[0] ?? '');
148
    }
149
150
    /**
151
     * Tell whether the URI represents a relative path.
152
     *
153
     * @param Psr7UriInterface|UriInterface $uri
154
     */
155 110
    public static function isRelativePath($uri): bool
156
    {
157 110
        $uri = self::filterUri($uri);
158 108
        $null = self::emptyComponentValue($uri);
159
160 108
        return $null === $uri->getScheme()
161 108
            && $null === $uri->getAuthority()
162 108
            && '/' !== ($uri->getPath()[0] ?? '');
163
    }
164
165
    /**
166
     * Tell whether both URI refers to the same document.
167
     *
168
     * @param Psr7UriInterface|UriInterface $uri
169
     * @param Psr7UriInterface|UriInterface $base_uri
170
     */
171 24
    public static function isSameDocument($uri, $base_uri): bool
172
    {
173 24
        $uri = self::normalize($uri);
174 22
        $base_uri = self::normalize($base_uri);
175
176 20
        return (string) $uri->withFragment($uri instanceof Psr7UriInterface ? '' : null)
177 20
            === (string) $base_uri->withFragment($base_uri instanceof Psr7UriInterface ? '' : null);
178
    }
179
180
    /**
181
     * Returns the URI origin property as defined by WHATWG URL living standard.
182
     *
183
     * {@see https://url.spec.whatwg.org/#origin}
184
     *
185
     * For non absolute URI the method will return null
186
     * For absolute URI without a defined host the opaque URI without the scheme is returned
187
     * For absolute URI with the file scheme the method will return null (as this is left to the implementation decision)
188
     * For absolute URI with a defined host it will return the scheme followed by the authority
189
     *
190
     * @param Psr7UriInterface|UriInterface $uri
191
     */
192 12
    public static function getOrigin($uri): ?string
193
    {
194 12
        if (!self::isAbsolute($uri)) {
195 2
            return null;
196
        }
197
198 10
        if (self::SCHEME_FILE === $uri->getScheme()) {
199 2
            return null;
200
        }
201
202 8
        $null = self::emptyComponentValue($uri);
203 8
        if ($null !== $uri->getHost()) {
204 6
            return (string) $uri->withFragment($null)->withQuery($null)->withPath('');
205
        }
206
207 4
        $newUri = Uri::createFromString($uri->getPath())->withQuery($uri->getQuery())->withFragment($uri->getFragment());
208 4
        if (self::SCHEME_BLOB === $uri->getScheme()) {
209 2
            return self::getOrigin($newUri);
210
        }
211
212 2
        return (string) $newUri;
213
    }
214
}
215