Completed
Push — master ( b0bce0...c1c6ff )
by ignace nyamagana
04:32
created

src/Modifiers/Resolve.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * League.Uri (http://uri.thephpleague.com)
4
 *
5
 * @package   League.uri
6
 * @author    Ignace Nyamagana Butera <[email protected]>
7
 * @copyright 2013-2015 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\Components\Path;
15
use League\Uri\Interfaces\Uri;
16
use League\Uri\Modifiers\Filters\Uri as UriFilter;
17
use Psr\Http\Message\UriInterface;
18
19
/**
20
 * Resolve an URI according to a base URI using
21
 * RFC3986 rules
22
 *
23
 * @package League.uri
24
 * @author  Ignace Nyamagana Butera <[email protected]>
25
 * @since   4.0.0
26
 */
27
class Resolve extends AbstractUriModifier
28
{
29
    use UriFilter;
30
31
    /**
32
     * New instance
33
     *
34
     * @param Uri|UriInterface $uri
35
     */
36 150
    public function __construct($uri)
37
    {
38 150
        $this->assertUriObject($uri);
39 150
        $this->uri = $uri;
0 ignored issues
show
Documentation Bug introduced by
It seems like $uri can also be of type object<League\Uri\Interfaces\Uri>. However, the property $uri is declared as type object<Psr\Http\Message\UriInterface>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
40 150
    }
41
42
    /**
43
     * Return a Uri object modified according to the modifier
44
     *
45
     * @param Uri|UriInterface $payload
46
     *
47
     * @return Uri|UriInterface
48
     */
49 150
    public function __invoke($payload)
50
    {
51 150
        $this->assertUriObject($payload);
52 150
        if ('' !== $payload->getScheme()) {
53 6
            return $payload;
54
        }
55
56 144
        if ('' !== $payload->getAuthority()) {
57 3
            return $payload->withScheme($this->uri->getScheme());
58
        }
59
60 141
        $userInfo = explode(':', $this->uri->getUserInfo(), 2);
61 141
        $components = $this->resolvePathAndQuery($payload->getPath(), $payload->getQuery());
62
63
        return $payload
64 141
            ->withPath($this->formatPath($components['path']))
65 141
            ->withQuery($components['query'])
66 141
            ->withHost($this->uri->getHost())
67 141
            ->withPort($this->uri->getPort())
68 141
            ->withUserInfo((string) array_shift($userInfo), array_shift($userInfo))
69 141
            ->withScheme($this->uri->getScheme());
70
    }
71
72
    /**
73
     * Resolve the URI for a Authority-less payload URI
74
     *
75
     * @param string $path  the payload path component
76
     * @param string $query the payload query component
77
     *
78
     * @return string[]
79
     */
80 141
    protected function resolvePathAndQuery($path, $query)
81
    {
82 141
        $components = ['path' => $path, 'query' => $query];
83
84 141
        if ('' === $components['path']) {
85 9
            $components['path'] = $this->uri->getPath();
86 9
            if ('' === $components['query']) {
87 6
                $components['query'] = $this->uri->getQuery();
88 4
            }
89
90 9
            return $components;
91
        }
92
93 132
        if (0 !== strpos($components['path'], '/')) {
94 123
            $components['path'] = $this->mergePath($components['path']);
95 82
        }
96
97 132
        return $components;
98
    }
99
100
    /**
101
     * Merging Relative URI path with Base URI path
102
     *
103
     * @param string $path
104
     *
105
     * @return string
106
     */
107 123
    protected function mergePath($path)
108
    {
109 123
        $basePath = $this->uri->getPath();
110 123
        if ('' !== $this->uri->getAuthority() && '' === $basePath) {
111 3
            return (string) (new Path($path))->withLeadingSlash();
112
        }
113
114 120
        if ('' !== $basePath) {
115 120
            $segments = explode('/', $basePath);
116 120
            array_pop($segments);
117 120
            $path = implode('/', $segments).'/'.$path;
118 80
        }
119
120 120
        return $path;
121
    }
122
123
    /**
124
     * Format the resolved path
125
     *
126
     * @param string $path
127
     *
128
     * @return string
129
     */
130 141
    protected function formatPath($path)
131
    {
132 141
        $path = (new Path($path))->withoutDotSegments();
133 141
        if ('' !== $this->uri->getAuthority() && '' !== $path->__toString()) {
134 126
            $path = $path->withLeadingSlash();
135 84
        }
136
137 141
        return (string) $path;
138
    }
139
}
140