From 473ed1c926813f21daba835e1de0c97507219236 Mon Sep 17 00:00:00 2001 From: Michael Newton Date: Fri, 20 Oct 2023 09:45:35 -0600 Subject: [PATCH] add custom replacers where rules have parameters --- src/Rules/InNetwork.php | 34 +++++++++++++++++++++++++++------ src/Rules/Netv4.php | 31 +++++++++++++----------------- src/Rules/Netv6.php | 23 +++++++++++++--------- src/Rules/RoutableNetv4.php | 23 +++++++++++++--------- src/Rules/RoutableNetv6.php | 23 +++++++++++++--------- tests/Feature/InNetworkTest.php | 4 ++-- tests/Feature/Netv4Test.php | 4 ++-- tests/Feature/Netv6Test.php | 6 +++--- 8 files changed, 90 insertions(+), 58 deletions(-) diff --git a/src/Rules/InNetwork.php b/src/Rules/InNetwork.php index 23f478b..2a6e20e 100644 --- a/src/Rules/InNetwork.php +++ b/src/Rules/InNetwork.php @@ -32,13 +32,35 @@ public function doValidation(string $value, ...$parameters): bool public function message(): string { - if (isset($this->networks) && count($this->networks) > 1) { - return __('The :attribute field must be an IP address within the allowed networks'); + $message = __('The :attribute field must be an IP address within the :net network(s)'); + if (!$this->extended) { + $message = $this->replace($message, "", "", $this->networks); } - return sprintf( - __('The :attribute field must be an IP address within the %s network'), - $this->networks[0] ?? __('specified') - ); + return $message; + } + + /** + * Generate a nice list when multiple networks are supplied + */ + public function replace(string $message, string $attribute, string $rule, array $parameters): string + { + if (count($parameters) > 2) { + array_walk($parameters, function(&$v, $k) use ($parameters) { + if ($k < count($parameters) - 1) { + $v .= ','; + } + if ($k === count($parameters) - 2) { + $v .= ' or'; + } + }); + $nets = implode(" ", $parameters); + } elseif (count($parameters) === 2) { + $nets = implode(" or ", $parameters); + } else { + $nets = $parameters[0]; + } + + return str_replace(':net', $nets, $message); } } diff --git a/src/Rules/Netv4.php b/src/Rules/Netv4.php index ade4d2c..1592998 100644 --- a/src/Rules/Netv4.php +++ b/src/Rules/Netv4.php @@ -7,8 +7,6 @@ class Netv4 extends BaseRule { - private bool $validMask = true; - public function __construct( private ?int $minBits = Util::IPV4_RANGE_MIN, private ?int $maxBits = Util::IPV4_RANGE_MAX @@ -32,28 +30,25 @@ public function doValidation(string $value, ...$parameters): bool throw new InvalidArgumentException('Invalid network validation rule arguments'); } - $result = Util::validIPv4Network($value, $this->minBits, $this->maxBits); - if (!$result && str_contains($value, '/')) { - [, $mask] = explode('/', $value); - $this->validMask = Util::validRange($mask, $this->minBits, $this->maxBits); + return Util::validIPv4Network($value, $this->minBits, $this->maxBits); + } - return false; + public function message(): string + { + $message = __('The :attribute field must be an IPv4 network in CIDR notation'); + if (!$this->extended) { + $message = $this->replace($message, "", "", [$this->minBits, $this->maxBits]); } - return $result; + return $message; } - public function message(): string + public function replace(string $message, string $attribute, string $rule, array $parameters): string { - if (!$this->validMask) { - // this only works when validating with instance method - return sprintf( - __('The :attribute field must have a network mask between %d and %d bits'), - $this->minBits, - $this->maxBits - ); + if (count($parameters) === 2) { + $message .= vsprintf(__(' with a mask between %d and %d bits'), $parameters); } - return __('The :attribute field must be an IPv4 network in CIDR notation'); + return $message; } -} \ No newline at end of file +} diff --git a/src/Rules/Netv6.php b/src/Rules/Netv6.php index 76ccbce..11d8e3e 100644 --- a/src/Rules/Netv6.php +++ b/src/Rules/Netv6.php @@ -45,15 +45,20 @@ public function doValidation(string $value, ...$parameters): bool public function message(): string { - if (!$this->validMask) { - // this only works when validating with instance method - return sprintf( - __('The :attribute field must have a network mask between %d and %d bits'), - $this->minBits, - $this->maxBits - ); + $message = __('The :attribute field must be an IPv6 network in CIDR notation'); + if (!$this->extended) { + $message = $this->replace($message, "", "", [$this->minBits, $this->maxBits]); } - return __('The :attribute field must be an IPv6 network in CIDR notation'); + return $message; } -} \ No newline at end of file + + public function replace(string $message, string $attribute, string $rule, array $parameters): string + { + if (count($parameters) === 2) { + $message .= vsprintf(__(' with a mask between %d and %d bits'), $parameters); + } + + return $message; + } +} diff --git a/src/Rules/RoutableNetv4.php b/src/Rules/RoutableNetv4.php index aafc2f0..f4ce33f 100644 --- a/src/Rules/RoutableNetv4.php +++ b/src/Rules/RoutableNetv4.php @@ -45,15 +45,20 @@ public function doValidation(string $value, ...$parameters): bool public function message(): string { - if (!$this->validMask) { - // this only works when validating with instance method - return sprintf( - __('The :attribute field must have a network mask between %d and %d bits'), - $this->minBits, - $this->maxBits - ); + $message = __('The :attribute field must be a routable IPv4 network in CIDR notation'); + if (!$this->extended) { + $message = $this->replace($message, "", "", [$this->minBits, $this->maxBits]); } - return __('The :attribute field must be a routable IPv4 network in CIDR notation'); + return $message; } -} \ No newline at end of file + + public function replace(string $message, string $attribute, string $rule, array $parameters): string + { + if (count($parameters) === 2) { + $message .= vsprintf(__(' with a mask between %d and %d bits'), $parameters); + } + + return $message; + } +} diff --git a/src/Rules/RoutableNetv6.php b/src/Rules/RoutableNetv6.php index 9d9e9e9..2574ca2 100644 --- a/src/Rules/RoutableNetv6.php +++ b/src/Rules/RoutableNetv6.php @@ -45,15 +45,20 @@ public function doValidation(string $value, ...$parameters): bool public function message(): string { - if (!$this->validMask) { - // this only works when validating with instance method - return sprintf( - __('The :attribute field must have a network mask between %d and %d bits'), - $this->minBits, - $this->maxBits - ); + $message = __('The :attribute field must be a routable IPv6 network in CIDR notation'); + if (!$this->extended) { + $message = $this->replace($message, "", "", [$this->minBits, $this->maxBits]); } - return __('The :attribute field must be a routable IPv6 network in CIDR notation'); + return $message; } -} \ No newline at end of file + + public function replace(string $message, string $attribute, string $rule, array $parameters): string + { + if (count($parameters) === 2) { + $message .= vsprintf(__(' with a mask between %d and %d bits'), $parameters); + } + + return $message; + } +} diff --git a/tests/Feature/InNetworkTest.php b/tests/Feature/InNetworkTest.php index eeda37a..2bd4504 100644 --- a/tests/Feature/InNetworkTest.php +++ b/tests/Feature/InNetworkTest.php @@ -66,7 +66,7 @@ public function instanceAccepts(): void public function stringRejectsIpv4(): void { $this->expectException(ValidationException::class); - $this->expectExceptionMessage('The input test field must be an IP address within the specified network'); + $this->expectExceptionMessage('The input test field must be an IP address within the 10.0.0.0/8 network'); Validator::validate( ['input_test' => '172.16.0.56'], ['input_test' => 'in_network:10.0.0.0/8'] @@ -79,7 +79,7 @@ public function stringRejectsIpv4(): void public function stringRejectsIpv6(): void { $this->expectException(ValidationException::class); - $this->expectExceptionMessage('The input test field must be an IP address within the specified network'); + $this->expectExceptionMessage('The input test field must be an IP address within the 2601:44ec:a425e::/64 network'); Validator::validate( ['input_test' => '2608:445d:2183:ce42::582c'], ['input_test' => 'in_network:2601:44ec:a425e::/64'] diff --git a/tests/Feature/Netv4Test.php b/tests/Feature/Netv4Test.php index 18c56d9..ce523a0 100644 --- a/tests/Feature/Netv4Test.php +++ b/tests/Feature/Netv4Test.php @@ -66,7 +66,7 @@ public function instanceAcceptsUnbounded(): void public function stringRejectsBounded(): void { $this->expectException(ValidationException::class); - $this->expectExceptionMessage('The input test field must be an IPv4 network in CIDR notation'); + $this->expectExceptionMessage('The input test field must be an IPv4 network in CIDR notation with a mask between 20 and 24 bits'); Validator::validate( ['input_test' => $this->faker->ipv4 . '/28'], ['input_test' => 'netv4:20,24'] @@ -92,7 +92,7 @@ public function stringRejectsUnbounded(): void public function instanceRejectsBounded(): void { $this->expectException(ValidationException::class); - $this->expectExceptionMessage('The input test field must have a network mask between 20 and 24 bits'); + $this->expectExceptionMessage('The input test field must be an IPv4 network in CIDR notation with a mask between 20 and 24 bits'); Validator::validate( ['input_test' => $this->faker->ipv4 . '/28'], ['input_test' => new Rules\Netv4(20, 24)] diff --git a/tests/Feature/Netv6Test.php b/tests/Feature/Netv6Test.php index ab5f3a0..1d46ebc 100644 --- a/tests/Feature/Netv6Test.php +++ b/tests/Feature/Netv6Test.php @@ -66,7 +66,7 @@ public function instanceAcceptsUnbounded(): void public function stringRejectsBounded(): void { $this->expectException(ValidationException::class); - $this->expectExceptionMessage('The input test field must be an IPv6 network in CIDR notation'); + $this->expectExceptionMessage('The input test field must be an IPv6 network in CIDR notation with a mask between 60 and 64 bits'); Validator::validate( ['input_test' => $this->faker->ipv6 . '/48'], ['input_test' => 'netv6:60,64'] @@ -92,7 +92,7 @@ public function stringRejectsUnbounded(): void public function instanceRejectsBounded(): void { $this->expectException(ValidationException::class); - $this->expectExceptionMessage('The input test field must have a network mask between 60 and 64 bits'); + $this->expectExceptionMessage('The input test field must be an IPv6 network in CIDR notation with a mask between 60 and 64 bits'); Validator::validate( ['input_test' => $this->faker->ipv6 . '/48'], ['input_test' => new Rules\Netv6(60, 64)] @@ -105,7 +105,7 @@ public function instanceRejectsBounded(): void public function instanceRejectsUnbounded(): void { $this->expectException(ValidationException::class); - $this->expectExceptionMessage('The input test field must have a network mask between 0 and 128 bits'); + $this->expectExceptionMessage('The input test field must be an IPv6 network in CIDR notation with a mask between 0 and 128 bits'); Validator::validate( ['input_test' => $this->faker->ipv6 . '/200'], ['input_test' => new Rules\Netv6()]