Completed
Push — master ( 5e61d1...b0bce0 )
by ignace nyamagana
05:19
created

Relativize::hostToAscii()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * League.Uri (http://uri.thephpleague.com)
4
 *
5
 * @package   League.uri
6
 * @author    Ignace Nyamagana Butera <[email protected]>
7
 * @copyright 2016 Ignace Nyamagana Butera
8
 * @license   https://github.com/thephpleague/uri/blob/master/LICENSE (MIT License)
9
 * @version   4.2.0
10
 * @link      https://github.com/thephpleague/uri/
11
 */
12
namespace League\Uri\Modifiers;
13
14
use League\Uri\Interfaces\Uri;
15
use Psr\Http\Message\UriInterface;
16
17
/**
18
 * Resolve an URI according to a base URI using
19
 * RFC3986 rules
20
 *
21
 * @package League.uri
22
 * @author  Ignace Nyamagana Butera <[email protected]>
23
 * @since   4.2.0
24
 */
25
class Relativize extends AbstractUriModifier
26
{
27
    /**
28
     * Base URI
29
     *
30
     * @var Uri|UriInterface
31
     */
32
    protected $uri;
33
34
    /**
35
     * New instance
36
     *
37
     * @param Uri|UriInterface $uri
38
     */
39 102
    public function __construct($uri)
40
    {
41 102
        $this->assertUriObject($uri);
42 102
        $this->uri = $this->hostToAscii($uri);
43 102
    }
44
45 102
    protected function hostToAscii($uri)
46
    {
47 102
        static $modifier;
48 102
        if (null === $modifier) {
49 3
            $modifier = new HostToAscii();
50 2
        }
51
52 102
        return $modifier($uri);
53
    }
54
55
    /**
56
     * Return a Uri object modified according to the modifier
57
     *
58
     * @param Uri|UriInterface $payload
59
     *
60
     * @return Uri|UriInterface
61
     */
62 102
    public function __invoke($payload)
63
    {
64 102
        $this->assertUriObject($payload);
65 102
        $payload_normalized = $this->hostToAscii($payload);
66
67 102
        if ($this->uri->getScheme() !== $payload_normalized->getScheme()
68 102
            || $this->uri->getAuthority() !== $payload_normalized->getAuthority()
69 68
        ) {
70 33
            return $payload;
71
        }
72
73 69
        $path = $this->relativizePath($payload->getPath());
74
75
        return $payload
76 69
            ->withScheme('')
77 69
            ->withPort(null)
78 69
            ->withUserInfo('')
79 69
            ->withHost('')
80 69
            ->withPath($this->formatPath($path));
81
    }
82
83
    /**
84
     * Relative the URI for a authority-less payload URI
85
     *
86
     * @param string $path
87
     *
88
     * @return string
89
     */
90 69
    protected function relativizePath($path)
91
    {
92 69
        $segments = $this->getSegments($path);
93 69
        $basename = array_pop($segments);
94 69
        $basePath = $this->uri->getPath();
95 69
        if ($basePath === $path) {
96 18
            return $basename;
97
        }
98
99 51
        $baseSegments = $this->getSegments($basePath);
100 51
        array_pop($baseSegments);
101 51
        foreach ($baseSegments as $offset => $segment) {
102 48
            if (!isset($segments[$offset]) || $segment !== $segments[$offset]) {
103 24
                break;
104
            }
105 33
            unset($baseSegments[$offset], $segments[$offset]);
106 34
        }
107 51
        $segments[] = $basename;
108
109 51
        return str_repeat('../', count($baseSegments)).implode('/', $segments);
110
    }
111
112
    /**
113
     * returns the path segments
114
     *
115
     * @param string $path
116
     *
117
     * @return array
118
     */
119 69
    protected function getSegments($path)
120
    {
121 69
        if ('' !== $path && '/' === $path[0]) {
122 66
            $path = substr($path, 1);
123 44
        }
124
125 69
        return explode('/', $path);
126
    }
127
128
    /**
129
     * Post formatting the path to keep a valid URI
130
     *
131
     * @param string $path
132
     *
133
     * @return string
134
     */
135 69
    protected function formatPath($path)
136
    {
137 69
        if ('' === $path) {
138 9
            $basePath = $this->uri->getPath();
139
140 9
            return in_array($basePath, ['', '/']) ? $basePath : './';
141
        }
142
143 60
        if (false === ($colonPos = strpos($path, ':'))) {
144 54
            return $path;
145
        }
146
147 6
        $slashPos = strpos($path, '/');
148 6
        if (false === $slashPos || $colonPos < $slashPos) {
149 3
            return "./$path";
150
        }
151
152 3
        return $path;
153
    }
154
}
155