Completed
Push — master ( 898500...e76c1b )
by Nikolas
03:28
created

Url::getPort()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace rtens\domin\delivery\web;
3
4
class Url {
5
6
    const HOST_PREFIX = '//';
7
    const PORT_SEPARATOR = ':';
8
    const SCHEME_SEPARATOR = ':';
9
    const QUERY_STRING_SEPARATOR = '?';
10
    const FRAGMENT_SEPARATOR = '#';
11
    const MAX_PARAM_LENGTH = 512;
12
13
    /** @var null|string */
14
    private $scheme;
15
16
    /** @var null|string */
17
    private $host;
18
19
    /** @var null|int */
20
    private $port;
21
22
    /** @var array */
23
    private $path;
24
25
    /** @var array */
26
    private $parameters;
27
28
    /** @var string|null */
29
    private $fragment;
30
31
    /**
32
     * @param string $scheme
33
     * @param string $host
34
     * @param int $port
35
     * @param array $path
36
     * @param array $parameters
37
     * @param string|null $fragment
38
     */
39
    function __construct($scheme = 'http', $host = null, $port = 80, array $path = [], $parameters = [], $fragment = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
40
        $this->scheme = $scheme;
41
        $this->host = $host;
42
        $this->port = $port;
43
        $this->path = $path;
44
        $this->parameters = $parameters;
45
        $this->fragment = $fragment;
46
    }
47
48
    /**
49
     * @param array|string $path
50
     * @param array $parameters
51
     * @param null|string $fragment
52
     * @return Url
53
     */
54
    public static function relative($path, array $parameters = [], $fragment = null) {
55
        return new Url(null, null, null, (array)$path, $parameters, $fragment);
56
    }
57
58
    /**
59
     * @return Url
60
     */
61
    private function copy() {
62
        return new Url(
63
            $this->scheme,
64
            $this->host,
65
            $this->port,
66
            $this->path,
67
            $this->parameters,
68
            $this->fragment
69
        );
70
    }
71
72
    /**
73
     * @return null|string
74
     */
75
    public function getScheme() {
76
        return $this->scheme;
77
    }
78
    /**
79
     * @return null|string
80
     */
81
    public function getHost() {
82
        return $this->host;
83
    }
84
    /**
85
     * @return int|null
86
     */
87
    public function getPort() {
88
        return $this->port;
89
    }
90
    /**
91
     * @return array
92
     */
93
    public function getParameters() {
94
        return $this->parameters;
95
    }
96
97
    /**
98
     * @param array $parameters
99
     * @return static
100
     */
101
    public function withParameters(array $parameters) {
102
        $newUrl = $this->copy();
103
        $newUrl->parameters = $parameters;
104
        return $newUrl;
105
    }
106
    /**
107
     * @param string $key
108
     * @param mixed $value
109
     * @return static
110
     */
111
    public function withParameter($key, $value) {
112
        $newUrl = $this->copy();
113
        $newUrl->parameters[$key] = $value;
114
        return $newUrl;
115
    }
116
    /**
117
     * @return null|string
118
     */
119
    public function getFragment() {
120
        return $this->fragment;
121
    }
122
    /**
123
     * @return array
124
     */
125
    public function getPath() {
126
        return $this->path;
127
    }
128
    /**
129
     * @param array $path
130
     * @return static
131
     */
132
    public function withPath(array $path) {
133
        $url = $this->copy();
134
        $url->path = $path;
135
        return $url;
136
    }
137
138
    /**
139
     * @param array $path
140
     * @return Url
141
     */
142
    public function append(array $path) {
143
        $url = $this->copy();
144
        $url->path = array_merge($url->path, $path);
145
        return $url;
146
    }
147
148
    public function __toString() {
149
        $queries = array();
150
        foreach ($this->flattenParams($this->parameters) as $key => $value) {
151
            $queries[] = $key . '=' . urlencode($value);
152
        }
153
        $port = $this->port ? self::PORT_SEPARATOR . $this->port : '';
154
        $scheme = $this->scheme ? $this->scheme . self::SCHEME_SEPARATOR : '';
155
        $server = $this->host ? $scheme . self::HOST_PREFIX . $this->host . $port : '';
156
        return
157
            $server
158
            . implode('/', $this->path)
159
            . ($queries ? self::QUERY_STRING_SEPARATOR . implode('&', $queries) : '')
160
            . ($this->fragment ? self::FRAGMENT_SEPARATOR . $this->fragment : '');
161
    }
162
163
    private function flattenParams($parameters, $i = 0) {
164
        $flat = [];
165
        foreach ($parameters as $key => $value) {
166
            if (is_array($value)) {
167
                foreach ($this->flattenParams($value, $i + 1) as $subKey => $subValue) {
168
                    $flatKey = $i ? "{$key}][{$subKey}" : "{$key}[{$subKey}]";
169
                    $flat = $this->set($flat, $flatKey, $subValue);
170
                }
171
            } else {
172
                $flat = $this->set($flat, $key, $value);
173
            }
174
        }
175
        return $flat;
176
    }
177
178
    private function set(array $map, $key, $value) {
179
        $cabBeCasted = !is_object($value) || method_exists($value, '__toString');
180
        if ($cabBeCasted && strlen((string)$value) <= self::MAX_PARAM_LENGTH) {
181
            $map[$key] = $value;
182
        }
183
        return $map;
184
    }
185
}