Skip to content

Commit 1c96ab0

Browse files
arogachevvjik
andauthored
Add more constants and shorcut methods (#65)
* Add more constants * Fix * Update changelog [skip ci] * Ready for review * Ready for review 2 * Update CHANGELOG.md Co-authored-by: Sergei Predvoditelev <[email protected]> * Update src/IpHelper.php Co-authored-by: Sergei Predvoditelev <[email protected]> * Update src/IpHelper.php Co-authored-by: Sergei Predvoditelev <[email protected]> * Update src/IpHelper.php Co-authored-by: Sergei Predvoditelev <[email protected]> --------- Co-authored-by: Sergei Predvoditelev <[email protected]>
1 parent e09c265 commit 1c96ab0

File tree

5 files changed

+94
-8
lines changed

5 files changed

+94
-8
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
## 1.1.1 under development
44

5-
- no changes in this release.
5+
- New #65: Add `IP_PATTERN` and `IP_REGEXP` constants to `IpHelper` for checking IP of both IPv4 and IPv6 versions
6+
(@arogachev)
7+
- New #65: Add `NEGATION_CHARACTER` constant to `IpRanges` used to negate ranges (@arogachev)
8+
- New #65: Add `isIpv4()`, `isIpv6()`, `isIp()` methods to `IpHelper` (@arogachev)
69

710
## 1.1.0 August 06, 2024
811

src/DnsHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use RuntimeException;
88

99
/**
10-
* DnsHelper contains static methods to work with DNS.
10+
* `DnsHelper` contains static methods to work with DNS.
1111
*/
1212
final class DnsHelper
1313
{

src/IpHelper.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use function strlen;
1313

1414
/**
15-
* DnsHelper contains static methods to work with IPs.
15+
* `IpHelper` contains static methods to work with IPs.
1616
*/
1717
final class IpHelper
1818
{
@@ -21,7 +21,7 @@ final class IpHelper
2121

2222
/**
2323
* IPv4 address pattern. This pattern is PHP and JavaScript compatible.
24-
* Allows to define your own IP regexp eg. `'/^'.IpHelper::IPV4_PATTERN.'/(\d+)$/'`.
24+
* Allows to define your own IP regexp e.g. `'/^'.IpHelper::IPV4_PATTERN.'/(\d+)$/'`.
2525
*/
2626
public const IPV4_PATTERN = '((2(5[0-5]|[0-4]\d)|1\d{2}|[1-9]?\d)\.){3}(2(5[0-5]|[0-4]\d)|1\d{2}|[1-9]?\d)';
2727
/**
@@ -30,7 +30,7 @@ final class IpHelper
3030
public const IPV4_REGEXP = '/^' . self::IPV4_PATTERN . '$/';
3131
/**
3232
* IPv6 address pattern. This pattern is PHP and Javascript compatible.
33-
* Allows to define your own IP regexp eg. `'/^'.IpHelper::IPV6_PATTERN.'/(\d+)$/'`.
33+
* Allows to define your own IP regexp e.g. `'/^'.IpHelper::IPV6_PATTERN.'/(\d+)$/'`.
3434
*/
3535
public const IPV6_PATTERN = '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:' . self::IPV4_PATTERN . ')';
3636
/**
@@ -45,6 +45,30 @@ final class IpHelper
4545
* The length of IPv4 address in bits.
4646
*/
4747
public const IPV4_ADDRESS_LENGTH = 32;
48+
/**
49+
* IP address pattern (for both IPv4 and IPv6 versions). This pattern is PHP and Javascript compatible.
50+
* Allows to define your own IP regexp.
51+
*/
52+
public const IP_PATTERN = '((' . self::IPV4_PATTERN . ')|(' . self::IPV6_PATTERN . '))';
53+
/**
54+
* IP address regexp (for both IPv4 and IPv6 versions). This regexp is PHP and JavaScript compatible.
55+
*/
56+
public const IP_REGEXP = '/^' . self::IP_PATTERN . '$/';
57+
58+
public static function isIpv4(string $value): bool
59+
{
60+
return preg_match(self::IPV4_REGEXP, $value) === 1;
61+
}
62+
63+
public static function isIpv6(string $value): bool
64+
{
65+
return preg_match(self::IPV6_REGEXP, $value) === 1;
66+
}
67+
68+
public static function isIp(string $value): bool
69+
{
70+
return preg_match(self::IP_REGEXP, $value) === 1;
71+
}
4872

4973
/**
5074
* Gets the IP version.

src/IpRanges.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ final class IpRanges
2424
public const LOCALHOST = 'localhost';
2525
public const DOCUMENTATION = 'documentation';
2626
public const SYSTEM = 'system';
27+
/**
28+
* Negation character used to negate ranges
29+
*/
30+
public const NEGATION_CHARACTER = '!';
2731

2832
/**
2933
* Default network aliases.
@@ -152,7 +156,8 @@ private function prepareRanges(array $ranges): array
152156
$replacements = $this->prepareRanges($this->networks[$range]);
153157
foreach ($replacements as &$replacement) {
154158
[$isReplacementNegated, $replacement] = $this->parseNegatedRange($replacement);
155-
$result[] = ($isRangeNegated && !$isReplacementNegated ? '!' : '') . $replacement;
159+
$result[] = ($isRangeNegated && !$isReplacementNegated ? self::NEGATION_CHARACTER : '')
160+
. $replacement;
156161
}
157162
} else {
158163
$result[] = $string;
@@ -173,7 +178,7 @@ private function prepareRanges(array $ranges): array
173178
*/
174179
private function parseNegatedRange(string $string): array
175180
{
176-
$isNegated = strpos($string, '!') === 0;
177-
return [$isNegated, $isNegated ? substr($string, strlen('!')) : $string];
181+
$isNegated = strpos($string, self::NEGATION_CHARACTER) === 0;
182+
return [$isNegated, $isNegated ? substr($string, strlen(self::NEGATION_CHARACTER)) : $string];
178183
}
179184
}

tests/IpHelperTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,60 @@
1010

1111
final class IpHelperTest extends TestCase
1212
{
13+
public function dataIsIpv4(): array
14+
{
15+
return [
16+
'valid' => ['192.168.10.11', true],
17+
'invalid, small length' => ['1.1.1', false],
18+
'invalid, letters' => ['not.an.ip', false],
19+
'invalid, IPv6' => ['2008:fa::1', false],
20+
];
21+
}
22+
23+
/**
24+
* @dataProvider dataIsIpv4
25+
*/
26+
public function testIsIpv4(string $ip, bool $expected): void
27+
{
28+
$this->assertSame($expected, IpHelper::isIpv4($ip));
29+
}
30+
31+
public function dataIsIpV6(): array
32+
{
33+
return [
34+
'valid' => ['2008:fa::1', true],
35+
'invalid' => ['2008:fz::0', false],
36+
'invalid, subnet' => ['2008:fa::0:1/64', false],
37+
'invalid, IPv4' => ['192.168.10.11', false],
38+
];
39+
}
40+
41+
/**
42+
* @dataProvider dataIsIpV6
43+
*/
44+
public function testIsIpv6(string $ip, bool $expected): void
45+
{
46+
$this->assertSame($expected, IpHelper::isIpv6($ip));
47+
}
48+
49+
public function dataIsIp(): array
50+
{
51+
return [
52+
'valid, IPv4' => ['192.168.10.11', true],
53+
'valid, IPv6' => ['2008:fa::1', true],
54+
'invalid, IPv4' => ['1.1.1', false],
55+
'invalidm IPv6' => ['2008:fz::0', false],
56+
];
57+
}
58+
59+
/**
60+
* @dataProvider dataIsIp
61+
*/
62+
public function testIsIp(string $ip, bool $expected): void
63+
{
64+
$this->assertSame($expected, IpHelper::isIp($ip));
65+
}
66+
1367
/**
1468
* @dataProvider getIpVersionProvider
1569
*/

0 commit comments

Comments
 (0)