Completed
Push — master ( 542186...fb692e )
by ignace nyamagana
04:16
created

Formatter::__invoke()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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