Completed
Pull Request — master (#40)
by ignace nyamagana
11:26
created

Host::isIp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 2
eloc 2
nc 2
nop 0
crap 6
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\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
     * New instance
48
     *
49
     * @param null|string $host
50
     */
51 654
    public function __construct($host = null)
52
    {
53 654
        if (null !== $host) {
54 582
            $host = $this->validateString($host);
55 576
            $this->data = $this->validate($host);
56 538
            $this->setLiteral();
57 538
        }
58 610
    }
59
60
    /**
61
     * Returns whether or not the host is an IDN
62
     *
63 538
     * @return bool
64
     */
65 538
    public function isIdn()
66 538
    {
67
        return $this->isIdn;
68
    }
69
70
    /**
71 14
     * Returns whether or not the host is an IP address
72
     *
73 14
     * @return bool
74
     */
75
    public function isIp()
76
    {
77
        return $this->hostAsIpv4 || $this->hostAsIpv6;
78
    }
79
80
    /**
81
     * Returns whether or not the host is an IPv4 address
82
     *
83 576
     * @return bool
84
     */
85 576
    public function isIpv4()
86 576
    {
87 80
        return $this->hostAsIpv4;
88
    }
89
90 518
    /**
91
     * Returns whether or not the host is an IPv6 address
92
     *
93
     * @return bool
94
     */
95
    public function isIpv6()
96 2
    {
97
        return $this->hostAsIpv6;
98 2
    }
99 2
100
    /**
101
     * Returns whether or not the host has a ZoneIdentifier
102 2
     *
103
     * @return bool
104
     *
105
     * @see http://tools.ietf.org/html/rfc6874#section-4
106
     */
107
    public function hasZoneIdentifier()
108 476
    {
109
        return $this->hasZoneIdentifier;
110 476
    }
111
112
    /**
113
     * Host literal setter
114
     */
115
    protected function setLiteral()
116 558
    {
117
        $this->host = !$this->isIp() ? $this->__toString() : $this->data[0];
118 558
    }
119 136
120
    /**
121
     * Returns the instance literal representation
122 516
     * without encoding
123 50
     *
124
     * @return string
125
     */
126 470
    public function getLiteral()
127
    {
128
        return $this->host;
129
    }
130
131
    /**
132 70
     * validate the submitted data
133
     *
134 70
     * @param string $str
135 22
     *
136
     * @return array
137
     */
138 50
    protected function validate($str)
139 50
    {
140 50
        $res = $this->validateIpHost($str);
141 50
        if (!empty($res)) {
142
            return $res;
143
        }
144
145
        return $this->validateStringHost($str);
146
    }
147 50
148
    /**
149 50
     * Retrieves a single host label.
150 46
     *
151
     * Retrieves a single host label. If the label offset has not been set,
152
     * returns the default value provided.
153 44
     *
154
     * @param string $offset  the label offset
155
     * @param mixed  $default Default value to return if the offset does not exist.
156
     *
157
     * @return mixed
158
     */
159 496
    public function getLabel($offset, $default = null)
160
    {
161 496
        if (isset($this->data[$offset])) {
162 488
            return $this->isIdn ? $this->data[$offset] : idn_to_ascii($this->data[$offset]);
163 24
        }
164
165
        return $default;
166 472
    }
167
168
    /**
169
     * Returns an array representation of the host
170
     *
171
     * @return array
172 12
     */
173
    public function toArray()
174 12
    {
175 6
        return $this->convertToAscii($this->data, !$this->isIdn);
176
    }
177
178 6
    /**
179
     * Returns the instance string representation; If the
180
     * instance is not defined an empty string is returned
181
     *
182
     * @return string
183
     */
184
    public function __toString()
185
    {
186
        if (empty($this->data)) {
187
            return '';
188 498
        }
189
190 498
        if ($this->isIp()) {
191 2
            return $this->formatIp($this->data[0]);
192
        }
193 496
194
        return $this->formatComponentString($this->toArray(), $this->isAbsolute);
195
    }
196
197
    /**
198
     * Returns a host in his punycode encoded form
199
     *
200
     * This method MUST retain the state of the current instance, and return
201
     * an instance with the host transcoded using to ascii the RFC 3492 rules
202 508
     *
203
     * @see http://tools.ietf.org/html/rfc3492
204 508
     *
205 508
     * @return static
206 28
     */
207 28
    public function toAscii()
208 28
    {
209
        if ($this->isIp() || !$this->isIdn) {
210 508
            return $this;
211
        }
212
213
        return $this->modify($this->formatComponentString(
214
            $this->convertToAscii($this->data, $this->isIdn),
215
            $this->isAbsolute
216 40
        ));
217
    }
218 40
219 40
    /**
220 40
     * Returns a host in his IDN form
221 40
     *
222
     * This method MUST retain the state of the current instance, and return
223
     * an instance with the host in its IDN form using RFC 3492 rules
224
     *
225
     * @see http://tools.ietf.org/html/rfc3492
226
     *
227
     * @return static
228
     */
229
    public function toUnicode()
230
    {
231
        if ($this->isIp() || $this->isIdn) {
232
            return $this;
233
        }
234
235
        return $this->modify($this->formatComponentString($this->data, $this->isAbsolute));
236
    }
237
238
    /**
239
     * @inheritdoc
240
     */
241
    protected static function formatComponentString($data, $type)
242
    {
243
        $hostname = implode(static::$separator, array_reverse(static::validateIterator($data)));
244
        if (self::IS_ABSOLUTE == $type) {
245
            return $hostname.static::$separator;
246
        }
247
248
        return $hostname;
249
    }
250
251
    /**
252
     * Return an host without its zone identifier according to RFC6874
253
     *
254
     * This method MUST retain the state of the current instance, and return
255
     * an instance without the host zone identifier according to RFC6874
256
     *
257
     * @see http://tools.ietf.org/html/rfc6874#section-4
258
     *
259
     * @return static
260
     */
261
    public function withoutZoneIdentifier()
262
    {
263
        if ($this->hasZoneIdentifier) {
264
            return $this->modify(substr($this->data[0], 0, strpos($this->data[0], '%')));
265
        }
266
267
        return $this;
268
    }
269
270
    /**
271
     * Validated the Host Label Count
272
     *
273
     * @param array $labels Host labels
274
     *
275
     * @throws InvalidArgumentException If the validation fails
276
     */
277
    protected function assertLabelsCount(array $labels)
278
    {
279
        if (127 <= count(array_merge($this->data, $labels))) {
280
            throw new InvalidArgumentException('Invalid Hostname, verify labels count');
281
        }
282
    }
283
284
    /**
285
     * set the FQDN property
286
     *
287
     * @param string $str
288
     *
289
     * @return string
290
     */
291
    protected function setIsAbsolute($str)
292
    {
293
        $this->isAbsolute = self::IS_RELATIVE;
294
        if ('.' == mb_substr($str, -1, 1, 'UTF-8')) {
295
            $this->isAbsolute = self::IS_ABSOLUTE;
296
            $str = mb_substr($str, 0, -1, 'UTF-8');
297
        }
298
299
        return $str;
300
    }
301
302
    /**
303
     * @inheritdoc
304
     */
305
    public function append($component)
306
    {
307
        return $this->newCollectionInstance(array_merge(
308
            $this->validateComponent($component)->toArray(),
309
            $this->toArray()
310
        ));
311
    }
312
313
    /**
314
     * @inheritdoc
315
     */
316
    public static function __set_state(array $properties)
317
    {
318
        $host = static::createFromArray($properties['data'], $properties['isAbsolute']);
319
        if (!$properties['isIdn']) {
320
            return $host->toAscii();
321
        }
322
323
        return $host;
324
    }
325
}
326