Skip to content

Add more constants and shorcut methods #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

## 1.1.1 under development

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

## 1.1.0 August 06, 2024

Expand Down
2 changes: 1 addition & 1 deletion src/DnsHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use RuntimeException;

/**
* DnsHelper contains static methods to work with DNS.
* `DnsHelper` contains static methods to work with DNS.
*/
final class DnsHelper
{
Expand All @@ -22,15 +22,15 @@
{
set_error_handler(static function (int $errorNumber, string $errorString) use ($hostname): bool {
throw new RuntimeException(
sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString,

Check warning on line 25 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ public static function existsMx(string $hostname) : bool { set_error_handler(static function (int $errorNumber, string $errorString) use($hostname) : bool { - throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString, $errorNumber); + throw new RuntimeException($errorString . sprintf('Failed to get DNS record "%s". ', $hostname), $errorNumber); }); $hostname = rtrim($hostname, '.') . '.'; $result = dns_get_record($hostname, DNS_MX);

Check warning on line 25 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ public static function existsMx(string $hostname) : bool { set_error_handler(static function (int $errorNumber, string $errorString) use($hostname) : bool { - throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString, $errorNumber); + throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname), $errorNumber); }); $hostname = rtrim($hostname, '.') . '.'; $result = dns_get_record($hostname, DNS_MX);
$errorNumber
);
});

$hostname = rtrim($hostname, '.') . '.';

Check warning on line 30 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "UnwrapRtrim": --- Original +++ New @@ @@ set_error_handler(static function (int $errorNumber, string $errorString) use($hostname) : bool { throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString, $errorNumber); }); - $hostname = rtrim($hostname, '.') . '.'; + $hostname = $hostname . '.'; $result = dns_get_record($hostname, DNS_MX); restore_error_handler(); return count($result) > 0;

Check warning on line 30 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ set_error_handler(static function (int $errorNumber, string $errorString) use($hostname) : bool { throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString, $errorNumber); }); - $hostname = rtrim($hostname, '.') . '.'; + $hostname = rtrim($hostname, '.'); $result = dns_get_record($hostname, DNS_MX); restore_error_handler(); return count($result) > 0;
$result = dns_get_record($hostname, DNS_MX);

restore_error_handler();

Check warning on line 33 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": --- Original +++ New @@ @@ }); $hostname = rtrim($hostname, '.') . '.'; $result = dns_get_record($hostname, DNS_MX); - restore_error_handler(); + return count($result) > 0; } /**

return count($result) > 0;
}
Expand All @@ -46,14 +46,14 @@
{
set_error_handler(static function (int $errorNumber, string $errorString) use ($hostname): bool {
throw new RuntimeException(
sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString,

Check warning on line 49 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ public static function existsA(string $hostname) : bool { set_error_handler(static function (int $errorNumber, string $errorString) use($hostname) : bool { - throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString, $errorNumber); + throw new RuntimeException($errorString . sprintf('Failed to get DNS record "%s". ', $hostname), $errorNumber); }); $result = dns_get_record($hostname, DNS_A); restore_error_handler();

Check warning on line 49 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ public static function existsA(string $hostname) : bool { set_error_handler(static function (int $errorNumber, string $errorString) use($hostname) : bool { - throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString, $errorNumber); + throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname), $errorNumber); }); $result = dns_get_record($hostname, DNS_A); restore_error_handler();
$errorNumber
);
});

$result = dns_get_record($hostname, DNS_A);

restore_error_handler();

Check warning on line 56 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": --- Original +++ New @@ @@ throw new RuntimeException(sprintf('Failed to get DNS record "%s". ', $hostname) . $errorString, $errorNumber); }); $result = dns_get_record($hostname, DNS_A); - restore_error_handler(); + return count($result) > 0; } /**

return count($result) > 0;
}
Expand All @@ -73,8 +73,8 @@
/**
* @psalm-suppress PossiblyUndefinedArrayOffset In this case `explode()` always returns an array with 2 elements.
*/
[, $hostnameOrEmail] = explode('@', $hostnameOrEmail, 2);

Check warning on line 76 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "IncrementInteger": --- Original +++ New @@ @@ /** * @psalm-suppress PossiblyUndefinedArrayOffset In this case `explode()` always returns an array with 2 elements. */ - [, $hostnameOrEmail] = explode('@', $hostnameOrEmail, 2); + [, $hostnameOrEmail] = explode('@', $hostnameOrEmail, 3); } return self::existsMx($hostnameOrEmail) || self::existsA($hostnameOrEmail); } }
}
return self::existsMx($hostnameOrEmail) || self::existsA($hostnameOrEmail);

Check warning on line 78 in src/DnsHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "LogicalOr": --- Original +++ New @@ @@ */ [, $hostnameOrEmail] = explode('@', $hostnameOrEmail, 2); } - return self::existsMx($hostnameOrEmail) || self::existsA($hostnameOrEmail); + return self::existsMx($hostnameOrEmail) && self::existsA($hostnameOrEmail); } }
}
}
30 changes: 27 additions & 3 deletions src/IpHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use function strlen;

/**
* DnsHelper contains static methods to work with IPs.
* `IpHelper` contains static methods to work with IPs.
*/
final class IpHelper
{
Expand All @@ -21,7 +21,7 @@ final class IpHelper

/**
* IPv4 address pattern. This pattern is PHP and JavaScript compatible.
* Allows to define your own IP regexp eg. `'/^'.IpHelper::IPV4_PATTERN.'/(\d+)$/'`.
* Allows to define your own IP regexp e.g. `'/^'.IpHelper::IPV4_PATTERN.'/(\d+)$/'`.
*/
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)';
/**
Expand All @@ -30,7 +30,7 @@ final class IpHelper
public const IPV4_REGEXP = '/^' . self::IPV4_PATTERN . '$/';
/**
* IPv6 address pattern. This pattern is PHP and Javascript compatible.
* Allows to define your own IP regexp eg. `'/^'.IpHelper::IPV6_PATTERN.'/(\d+)$/'`.
* Allows to define your own IP regexp e.g. `'/^'.IpHelper::IPV6_PATTERN.'/(\d+)$/'`.
*/
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 . ')';
/**
Expand All @@ -45,6 +45,30 @@ final class IpHelper
* The length of IPv4 address in bits.
*/
public const IPV4_ADDRESS_LENGTH = 32;
/**
* IP address pattern (for both IPv4 and IPv6 versions). This pattern is PHP and Javascript compatible.
* Allows to define your own IP regexp.
*/
public const IP_PATTERN = '((' . self::IPV4_PATTERN . ')|(' . self::IPV6_PATTERN . '))';
/**
* IP address regexp (for both IPv4 and IPv6 versions). This regexp is PHP and JavaScript compatible.
*/
public const IP_REGEXP = '/^' . self::IP_PATTERN . '$/';

public static function isIpv4(string $value): bool
{
return preg_match(self::IPV4_REGEXP, $value) === 1;
}

public static function isIpv6(string $value): bool
{
return preg_match(self::IPV6_REGEXP, $value) === 1;
}

public static function isIp(string $value): bool
{
return preg_match(self::IP_REGEXP, $value) === 1;
}

/**
* Gets the IP version.
Expand Down
11 changes: 8 additions & 3 deletions src/IpRanges.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ final class IpRanges
public const LOCALHOST = 'localhost';
public const DOCUMENTATION = 'documentation';
public const SYSTEM = 'system';
/**
* Negation character used to negate ranges
*/
public const NEGATION_CHARACTER = '!';

/**
* Default network aliases.
Expand Down Expand Up @@ -152,7 +156,8 @@ private function prepareRanges(array $ranges): array
$replacements = $this->prepareRanges($this->networks[$range]);
foreach ($replacements as &$replacement) {
[$isReplacementNegated, $replacement] = $this->parseNegatedRange($replacement);
$result[] = ($isRangeNegated && !$isReplacementNegated ? '!' : '') . $replacement;
$result[] = ($isRangeNegated && !$isReplacementNegated ? self::NEGATION_CHARACTER : '')
. $replacement;
}
} else {
$result[] = $string;
Expand All @@ -173,7 +178,7 @@ private function prepareRanges(array $ranges): array
*/
private function parseNegatedRange(string $string): array
{
$isNegated = strpos($string, '!') === 0;
return [$isNegated, $isNegated ? substr($string, strlen('!')) : $string];
$isNegated = strpos($string, self::NEGATION_CHARACTER) === 0;
return [$isNegated, $isNegated ? substr($string, strlen(self::NEGATION_CHARACTER)) : $string];
}
}
54 changes: 54 additions & 0 deletions tests/IpHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,60 @@

final class IpHelperTest extends TestCase
{
public function dataIsIpv4(): array
{
return [
'valid' => ['192.168.10.11', true],
'invalid, small length' => ['1.1.1', false],
'invalid, letters' => ['not.an.ip', false],
'invalid, IPv6' => ['2008:fa::1', false],
];
}

/**
* @dataProvider dataIsIpv4
*/
public function testIsIpv4(string $ip, bool $expected): void
{
$this->assertSame($expected, IpHelper::isIpv4($ip));
}

public function dataIsIpV6(): array
{
return [
'valid' => ['2008:fa::1', true],
'invalid' => ['2008:fz::0', false],
'invalid, subnet' => ['2008:fa::0:1/64', false],
'invalid, IPv4' => ['192.168.10.11', false],
];
}

/**
* @dataProvider dataIsIpV6
*/
public function testIsIpv6(string $ip, bool $expected): void
{
$this->assertSame($expected, IpHelper::isIpv6($ip));
}

public function dataIsIp(): array
{
return [
'valid, IPv4' => ['192.168.10.11', true],
'valid, IPv6' => ['2008:fa::1', true],
'invalid, IPv4' => ['1.1.1', false],
'invalidm IPv6' => ['2008:fz::0', false],
];
}

/**
* @dataProvider dataIsIp
*/
public function testIsIp(string $ip, bool $expected): void
{
$this->assertSame($expected, IpHelper::isIp($ip));
}

/**
* @dataProvider getIpVersionProvider
*/
Expand Down