Completed
Pull Request — master (#39)
by ignace nyamagana
03:06
created

Formatter::formatAuthority()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 8
Bugs 0 Features 0
Metric Value
c 8
b 0
f 0
dl 0
loc 20
ccs 14
cts 14
cp 1
rs 9.2
cc 4
eloc 12
nc 5
nop 1
crap 4
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.1.0
10
 * @link      https://github.com/thephpleague/uri/
11
 */
12
namespace League\Uri;
13
14
use InvalidArgumentException;
15
use League\Uri\Components\Host;
16
use League\Uri\Components\Query;
17
use League\Uri\Interfaces\Host as HostInterface;
18
use League\Uri\Interfaces\Query as QueryInterface;
19
use League\Uri\Interfaces\Uri;
20
use League\Uri\Interfaces\UriPart;
21
use League\Uri\Schemes\Generic\UriBuilderTrait;
22
use Psr\Http\Message\UriInterface;
23
24
/**
25
 * A class to manipulate URI and URI components output
26
 *
27
 * @package League.uri
28
 * @author  Ignace Nyamagana Butera <[email protected]>
29
 * @since   4.0.0
30
 */
31
class Formatter
32
{
33
    use UriBuilderTrait;
34
35
    const HOST_AS_UNICODE = 1;
36
37
    const HOST_AS_ASCII   = 2;
38
39
    /**
40
     * host encoding property
41
     *
42
     * @var int
43
     */
44
    protected $hostEncoding = self::HOST_AS_UNICODE;
45
46
    /**
47
     * query encoding property
48
     *
49
     * @var int
50
     */
51
    protected $queryEncoding = PHP_QUERY_RFC3986;
52
53
    /**
54
     * Query Parser object
55
     *
56
     * @var QueryParser
57
     */
58
    protected $queryParser;
59
60
    /**
61
     * query separator property
62
     *
63
     * @var string
64
     */
65
    protected $querySeparator = '&';
66
67
    /**
68
     * Should the query component be preserved
69
     *
70
     * @var bool
71
     */
72
    protected $preserveQuery = false;
73
74
    /**
75
     * Should the fragment component string be preserved
76
     *
77
     * @var bool
78
     */
79
    protected $preserveFragment = false;
80
81
    /**
82
     * New Instance
83
     */
84 48
    public function __construct()
85
    {
86 48
        $this->queryParser = new QueryParser();
87 48
    }
88
89
    /**
90
     * Host encoding setter
91
     *
92
     * @param int $encode a predefined constant value
93
     */
94 21
    public function setHostEncoding($encode)
95
    {
96 21
        if (!in_array($encode, [self::HOST_AS_UNICODE, self::HOST_AS_ASCII])) {
97 3
            throw new InvalidArgumentException('Unknown Host encoding rule');
98
        }
99 18
        $this->hostEncoding = $encode;
100 18
    }
101
102
    /**
103
     * Host encoding getter
104
     *
105
     * DEPRECATION WARNING! This method will be removed in the next major point release
106
     *
107
     * @deprecated deprecated since version 4.1
108
     *
109
     * @return int
110
     */
111
    public function getHostEncoding()
112
    {
113
        return $this->hostEncoding;
114
    }
115
116
    /**
117
     * Query encoding setter
118
     *
119
     * @param int $encode a predefined constant value
120
     */
121 9
    public function setQueryEncoding($encode)
122
    {
123 9
        if (!in_array($encode, [PHP_QUERY_RFC3986, PHP_QUERY_RFC1738])) {
124 3
            throw new InvalidArgumentException('Unknown Query encoding rule');
125
        }
126 6
        $this->queryEncoding = $encode;
127 6
    }
128
129
    /**
130
     * Query encoding getter
131
     *
132
     * DEPRECATION WARNING! This method will be removed in the next major point release
133
     *
134
     * @deprecated deprecated since version 4.1
135
     *
136
     * @return int
137
     */
138
    public function getQueryEncoding()
139
    {
140
        return $this->queryEncoding;
141
    }
142
143
    /**
144
     * Query separator setter
145
     *
146
     * @param string $separator
147
     */
148 15
    public function setQuerySeparator($separator)
149
    {
150 15
        $separator = filter_var($separator, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
151
152 15
        $this->querySeparator = trim($separator);
153 15
    }
154
155
    /**
156
     * Query separator getter
157
     *
158
     * DEPRECATION WARNING! This method will be removed in the next major point release
159
     *
160
     * @deprecated deprecated since version 4.1
161
     *
162
     * @return string
163
     */
164
    public function getQuerySeparator()
165
    {
166
        return $this->querySeparator;
167
    }
168
169
    /**
170
     * Whether we should preserve the Query component
171
     * regardless of its value.
172
     *
173
     * If set to true the query delimiter will be appended
174
     * to the URI regardless of the query string value
175
     *
176
     * @param bool $status
177
     */
178 3
    public function preserveQuery($status)
179
    {
180 3
        $this->preserveQuery = (bool) $status;
181 3
    }
182
183
    /**
184
     * Whether we should preserve the Fragment component
185
     * regardless of its value.
186
     *
187
     * If set to true the fragment delimiter will be appended
188
     * to the URI regardless of the query string value
189
     *
190
     * @param bool $status
191
     */
192 3
    public function preserveFragment($status)
193
    {
194 3
        $this->preserveFragment = (bool) $status;
195 3
    }
196
197
    /**
198
     * Format an object
199
     *
200
     * @see Formatter::format
201
     *
202
     * @param UriPart|Uri|UriInterface $input
203
     *
204
     * @return string
205
     */
206 39
    public function __invoke($input)
207
    {
208 39
        return $this->format($input);
209
    }
210
211
    /**
212
     * Format an object
213
     *
214
     * Format an object according to the formatter properties.
215
     * The object must implement one of the following interface:
216
     * <ul>
217
     * <li>League\Uri\Interfaces\Uri
218
     * <li>League\Uri\Interfaces\UriPart
219
     * <li>Psr\Http\Message\UriInterface
220
     * </ul>
221
     *
222
     * @param UriPart|Uri|UriInterface $input
223
     *
224
     * @return string
225
     */
226 42
    public function format($input)
227
    {
228 42
        if ($input instanceof UriPart) {
229 18
            return $this->formatUriPart($input);
230
        }
231
232 24
        if ($input instanceof Uri || $input instanceof UriInterface) {
233 21
            return $this->formatUri($input);
234
        }
235
236 3
        throw new InvalidArgumentException(
237 1
            'input must be an URI object or a League UriPart object'
238 2
        );
239
    }
240
241
    /**
242
     * Format a UriPart implemented object according to the Formatter properties
243
     *
244
     * @param UriPart $part
245
     *
246
     * @return string
247
     */
248 39
    protected function formatUriPart(UriPart $part)
249
    {
250 39
        if ($part instanceof QueryInterface) {
251 30
            return $this->queryParser->build($part->toArray(), $this->querySeparator, $this->queryEncoding);
252
        }
253
254 9
        if ($part instanceof HostInterface) {
255 6
            return $this->formatHost($part);
256
        }
257
258 3
        return $part->__toString();
259
    }
260
261
    /**
262
     * Format a Host according to the Formatter properties
263
     *
264
     * @param HostInterface $host
265
     *
266
     * @return string
267
     */
268 21
    protected function formatHost(HostInterface $host)
269
    {
270 21
        if (self::HOST_AS_ASCII == $this->hostEncoding) {
271 9
            return $host->toAscii()->__toString();
272
        }
273
274 12
        return $host->toUnicode()->__toString();
275
    }
276
277
    /**
278
     * Format an Uri according to the Formatter properties
279
     *
280
     * @param Uri|UriInterface $uri
281
     *
282
     * @return string
283
     */
284 21
    protected function formatUri($uri)
285
    {
286 21
        $scheme = $uri->getScheme();
287 21
        if ('' !== $scheme) {
288 18
            $scheme .= ':';
289 12
        }
290
291 21
        $auth = $this->formatAuthority($uri);
292
293 7
        return $scheme.$auth
294 21
            .$this->formatPath($uri->getPath(), $auth)
295 21
            .$this->formatQuery($uri)
296 21
            .$this->formatFragment($uri);
297
    }
298
299
    /**
300
     * Format a URI authority according to the Formatter properties
301
     *
302
     * @param Uri|UriInterface $uri
303
     *
304
     * @return string
305
     */
306 21
    protected function formatAuthority($uri)
307
    {
308 21
        if ('' == $uri->getHost()) {
309 6
            return '';
310
        }
311
312 15
        static $parser;
313 15
        if (!$parser) {
314 3
            $parser = new UriParser();
315 2
        }
316
317 15
        $components = $parser((string) $uri);
318 15
        $port = $components['port'];
319 15
        if (null !== $port) {
320 3
            $port = ':'.$port;
321 2
        }
322
323 15
        return '//'.$this->buildUserInfo($components['user'], $components['pass'])
324 15
            .$this->formatHost(new Host($components['host'])).$port;
325
    }
326
327
    /**
328
     * Format a URI Query component according to the Formatter properties
329
     *
330
     * @param Uri|UriInterface $uri
331
     *
332
     * @return string
333
     */
334 21
    protected function formatQuery($uri)
335
    {
336 21
        $query = $this->formatUriPart(new Query($uri->getQuery()));
337 21
        if ($this->preserveQuery || '' !== $query) {
338 15
            $query = '?'.$query;
339 10
        }
340
341 21
        return $query;
342
    }
343
344
    /**
345
     * Format a URI Fragment component according to the Formatter properties
346
     *
347
     * @param Uri|UriInterface $uri
348
     *
349
     * @return string
350
     */
351 21
    protected function formatFragment($uri)
352
    {
353 21
        $fragment = $uri->getFragment();
354 21
        if ($this->preserveFragment || '' != $fragment) {
355 15
            $fragment = '#'.$fragment;
356 10
        }
357
358 21
        return $fragment;
359
    }
360
}
361