Completed
Push — master ( 9db984...9898c1 )
by ignace nyamagana
02:48
created

Host::getLabels()   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 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
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\Components;
13
14
use InvalidArgumentException;
15
use League\Uri\Interfaces\Host as HostInterface;
16
17
/**
18
 * Value object representing a URI host component.
19
 *
20
 * @package League.uri
21
 * @author  Ignace Nyamagana Butera <[email protected]>
22
 * @since   1.0.0
23
 */
24
class Host extends AbstractHierarchicalComponent implements HostInterface
25
{
26
    use HostIpTrait;
27
28
    use HostnameInfoTrait;
29
30
    use HostnameTrait;
31
32
    /**
33
     * HierarchicalComponent delimiter
34
     *
35
     * @var string
36
     */
37
    protected static $separator = '.';
38
39
    /**
40
     * Host literal representation
41
     *
42
     * @var string
43
     */
44
    protected $host;
45
46
    /**
47
     * DEPRECATION WARNING! This method will be removed in the next major point release
48
     *
49
     * @deprecated deprecated since version 4.2
50
     *
51
     * return a new instance from an array or a traversable object
52
     *
53
     * @param \Traversable|string[] $data The segments list
54
     * @param int                   $type one of the constant IS_ABSOLUTE or IS_RELATIVE
55
     *
56
     * @throws InvalidArgumentException If $data is invalid
57
     * @throws InvalidArgumentException If $type is not a recognized constant
58
     *
59
     * @return static
60
     */
61
    public static function createFromArray($data, $type = self::IS_RELATIVE)
62
    {
63
        return self::createFromLabels($data, $type);
64
    }
65
66
    /**
67
     * return a new instance from an array or a traversable object
68
     *
69
     * @param \Traversable|string[] $data The segments list
70
     * @param int                   $type one of the constant IS_ABSOLUTE or IS_RELATIVE
71
     *
72
     * @throws InvalidArgumentException If $data is invalid
73
     * @throws InvalidArgumentException If $type is not a recognized constant
74
     *
75
     * @return static
76
     */
77 165
    public static function createFromLabels($data, $type = self::IS_RELATIVE)
78
    {
79 165
        static $type_list = [self::IS_ABSOLUTE => 1, self::IS_RELATIVE => 1];
80
81 165
        $data = static::validateIterator($data);
82 153
        if (!isset($type_list[$type])) {
83 3
            throw new InvalidArgumentException('Please verify the submitted constant');
84
        }
85
86 150
        if ([] === $data) {
87 12
            return new static();
88
        }
89
90 138
        if ([''] === $data) {
91 3
            return new static('');
92
        }
93
94 135
        return new static(static::format($data, $type));
95
    }
96
97
    /**
98
     * Return a formatted host string
99
     *
100
     * @param string[] $data The segments list
101
     * @param int      $type
102
     *
103
     * @return string
104
     */
105 889
    protected static function format(array $data, $type)
106
    {
107 889
        $hostname = implode(static::$separator, array_reverse($data));
108 889
        if (self::IS_ABSOLUTE === $type) {
109 36
            return $hostname.static::$separator;
110
        }
111
112 865
        return $hostname;
113
    }
114
115
    /**
116
     * New instance
117
     *
118
     * @param null|string $host
119
     */
120 1153
    public function __construct($host = null)
121
    {
122 1153
        $this->data = $this->validate($host);
123 1087
        $this->host = !$this->isIp() ? $this->__toString() : $this->data[0];
124 1087
    }
125
126
    /**
127
     * validate the submitted data
128
     *
129
     * @param string $str
130
     *
131
     * @return array
132
     */
133 1153
    protected function validate($str)
134
    {
135 1153
        if (null === $str) {
136 354
            return [];
137
        }
138
139 1033
        $str = $this->validateString($str);
140 1024
        if ('' === $str) {
141 54
            return [''];
142
        }
143
144 1012
        $res = $this->validateIpHost($str);
145 1012
        if (!empty($res)) {
146 120
            return $res;
147
        }
148
149 913
        return $this->validateStringHost($str);
150
    }
151
152
    /**
153
     * Return a new instance when needed
154
     *
155
     * @param array $data
156
     *
157
     * @return static
158
     */
159 45
    protected function newCollectionInstance(array $data)
160
    {
161 45
        return $this->createFromLabels($data, $this->isAbsolute);
162
    }
163
164
    /**
165
     * Returns whether or not the host is an IDN
166
     *
167
     * @return bool
168
     */
169 9
    public function isIdn()
170
    {
171 9
        return $this->isIdn;
172
    }
173
174
    /**
175
     * Returns whether or not the host is an IP address
176
     *
177
     * @return bool
178
     */
179 1087
    public function isIp()
180
    {
181 1087
        return $this->hostAsIpv4 || $this->hostAsIpv6;
182
    }
183
184
    /**
185
     * Returns whether or not the host is an IPv4 address
186
     *
187
     * @return bool
188
     */
189 39
    public function isIpv4()
190
    {
191 39
        return $this->hostAsIpv4;
192
    }
193
194
    /**
195
     * Returns whether or not the host is an IPv6 address
196
     *
197
     * @return bool
198
     */
199 39
    public function isIpv6()
200
    {
201 39
        return $this->hostAsIpv6;
202
    }
203
204
    /**
205
     * Returns whether or not the host has a ZoneIdentifier
206
     *
207
     * @return bool
208
     *
209
     * @see http://tools.ietf.org/html/rfc6874#section-4
210
     */
211 12
    public function hasZoneIdentifier()
212
    {
213 12
        return $this->hasZoneIdentifier;
214
    }
215
216
    /**
217
     * DEPRECATION WARNING! This method will be removed in the next major point release
218
     *
219
     * @deprecated deprecated since version 4.2
220
     *
221
     * Returns the instance literal representation
222
     * without encoding
223
     *
224
     * @return string
225
     */
226
    public function getLiteral()
227
    {
228
        return $this->host;
229
    }
230
231
    /**
232
     * Returns an array representation of the Host
233
     *
234
     * @return array
235
     */
236 880
    public function getLabels()
237
    {
238 880
        return $this->convertToAscii($this->data, !$this->isIdn);
239
    }
240
241
    /**
242
     * Retrieves a single host label.
243
     *
244
     * Retrieves a single host label. If the label offset has not been set,
245
     * returns the default value provided.
246
     *
247
     * @param string $offset  the label offset
248
     * @param mixed  $default Default value to return if the offset does not exist.
249
     *
250
     * @return mixed
251
     */
252 3
    public function getLabel($offset, $default = null)
253
    {
254 3
        if (isset($this->data[$offset])) {
255 3
            return $this->isIdn ? rawurldecode($this->data[$offset]) : idn_to_ascii($this->data[$offset]);
256
        }
257
258 3
        return $default;
259
    }
260
261
    /**
262
     * DEPRECATION WARNING! This method will be removed in the next major point release
263
     *
264
     * @deprecated deprecated since version 4.2
265
     *
266
     * Returns an array representation of the host
267
     *
268
     * @return array
269
     */
270
    public function toArray()
271
    {
272
        return $this->getLabels();
273
    }
274
275
    /**
276
     * @inheritdoc
277
     */
278 1069
    public function getContent()
279
    {
280 1069
        if ([] === $this->data) {
281 378
            return null;
282
        }
283
284 937
        if ($this->isIp()) {
285 81
            return $this->formatIp($this->data[0]);
286
        }
287
288 874
        return $this->format($this->getLabels(), $this->isAbsolute);
289
    }
290
291
    /**
292
     * @inheritdoc
293
     */
294 2
    public function __debugInfo()
295
    {
296 2
        return ['host' => $this->getContent()];
297
    }
298
299
    /**
300
     * @inheritdoc
301
     */
302 15
    public static function __set_state(array $properties)
303
    {
304 15
        $host = static::createFromLabels($properties['data'], $properties['isAbsolute']);
305 15
        $host->hostnameInfoLoaded = $properties['hostnameInfoLoaded'];
306 15
        $host->hostnameInfo = $properties['hostnameInfo'];
307
308 15
        return $host;
309
    }
310
311
    /**
312
     * Returns a host in his punycode encoded form
313
     *
314
     * This method MUST retain the state of the current instance, and return
315
     * an instance with the host transcoded using to ascii the RFC 3492 rules
316
     *
317
     * @see http://tools.ietf.org/html/rfc3492
318
     *
319
     * @return static
320
     */
321 216
    public function toAscii()
322
    {
323 216
        if ($this->isIp() || !$this->isIdn) {
324 144
            return $this;
325
        }
326
327 78
        return $this->modify($this->format(
328 78
            $this->convertToAscii($this->data, $this->isIdn),
329 78
            $this->isAbsolute
330 52
        ));
331
    }
332
333
    /**
334
     * Returns a host in his IDN form
335
     *
336
     * This method MUST retain the state of the current instance, and return
337
     * an instance with the host in its IDN form using RFC 3492 rules
338
     *
339
     * @see http://tools.ietf.org/html/rfc3492
340
     *
341
     * @return static
342
     */
343 81
    public function toUnicode()
344
    {
345 81
        if ($this->isIp() || $this->isIdn) {
346 69
            return $this;
347
        }
348
349 72
        return $this->modify($this->format($this->data, $this->isAbsolute));
350
    }
351
352
    /**
353
     * Return an host without its zone identifier according to RFC6874
354
     *
355
     * This method MUST retain the state of the current instance, and return
356
     * an instance without the host zone identifier according to RFC6874
357
     *
358
     * @see http://tools.ietf.org/html/rfc6874#section-4
359
     *
360
     * @return static
361
     */
362 18
    public function withoutZoneIdentifier()
363
    {
364 18
        if ($this->hasZoneIdentifier) {
365 9
            return $this->modify(substr($this->data[0], 0, strpos($this->data[0], '%')));
366
        }
367
368 9
        return $this;
369
    }
370
371
    /**
372
     * Validated the Host Label Count
373
     *
374
     * @param array $labels Host labels
375
     *
376
     * @throws InvalidArgumentException If the validation fails
377
     */
378 898
    protected function assertLabelsCount(array $labels)
379
    {
380 898
        if (127 <= count(array_merge($this->data, $labels))) {
381 3
            throw new InvalidArgumentException('Invalid Hostname, verify labels count');
382
        }
383 895
    }
384
385
    /**
386
     * set the FQDN property
387
     *
388
     * @param string $str
389
     *
390
     * @return string
391
     */
392 913
    protected function setIsAbsolute($str)
393
    {
394 913
        $this->isAbsolute = self::IS_RELATIVE;
395 913
        if ('.' === mb_substr($str, -1, 1, 'UTF-8')) {
396 42
            $this->isAbsolute = self::IS_ABSOLUTE;
397 42
            $str = mb_substr($str, 0, -1, 'UTF-8');
398 28
        }
399
400 913
        return $str;
401
    }
402
403
    /**
404
     * @inheritdoc
405
     */
406 30
    public function prepend($component)
407
    {
408 30
        return $this->createFromLabels(
409 30
                $this->validateComponent($component),
410 30
                $this->isAbsolute
411 30
            )->append($this->__toString());
412
    }
413
414
    /**
415
     * @inheritdoc
416
     */
417 60
    public function append($component)
418
    {
419 60
        return $this->createFromLabels(array_merge(
420 60
            iterator_to_array($this->validateComponent($component)),
421 60
            $this->getLabels()
422 60
        ), $this->isAbsolute);
423
    }
424
}
425