diff --git a/library/Rules/Each.php b/library/Rules/Each.php index 19397c0f0..66f4b8108 100644 --- a/library/Rules/Each.php +++ b/library/Rules/Each.php @@ -14,7 +14,6 @@ use Respect\Validation\Result; use Respect\Validation\Rules\Core\FilteredNonEmptyArray; -use function array_map; use function array_reduce; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] @@ -27,7 +26,10 @@ final class Each extends FilteredNonEmptyArray /** @param non-empty-array $input */ protected function evaluateNonEmptyArray(array $input): Result { - $children = array_map(fn ($item) => $this->rule->evaluate($item), $input); + $children = []; + foreach ($input as $key => $value) { + $children[] = $this->rule->evaluate($value)->withUnchangeableId((string) $key); + } $isValid = array_reduce($children, static fn ($carry, $childResult) => $carry && $childResult->isValid, true); if ($isValid) { return Result::passed($input, $this)->withChildren(...$children); diff --git a/tests/Pest.php b/tests/Pest.php index da5f77868..73ee8fade 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -12,7 +12,7 @@ use function PHPUnit\Framework\assertStringMatchesFormat; -/** @param array $messages */ +/** @param array $messages */ function expectAll(Closure $callback, string $message, string $fullMessage, array $messages): Closure { return function () use ($callback, $message, $fullMessage, $messages): void { @@ -27,7 +27,7 @@ function expectAll(Closure $callback, string $message, string $fullMessage, arra }; } -/** @param array $messages */ +/** @param array $messages */ function expectAllToMatch(Closure $callback, string $message, string $fullMessage, array $messages): Closure { return function () use ($callback, $message, $fullMessage, $messages): void { @@ -70,7 +70,7 @@ function expectFullMessage(Closure $callback, string $fullMessage): Closure }; } -/** @param array $messages */ +/** @param array $messages */ function expectMessages(Closure $callback, array $messages): Closure { return function () use ($callback, $messages): void { diff --git a/tests/feature/Issues/Issue1033Test.php b/tests/feature/Issues/Issue1033Test.php index 9914ebac8..246c30cc1 100644 --- a/tests/feature/Issues/Issue1033Test.php +++ b/tests/feature/Issues/Issue1033Test.php @@ -18,8 +18,8 @@ FULL_MESSAGE, [ '__root__' => 'Each item in `["A", "B", "B"]` must be valid', - 'equals.1' => '"A" must be equal to 1', - 'equals.2' => '"B" must be equal to 1', - 'equals.3' => '"B" must be equal to 1', + 0 => '"A" must be equal to 1', + 1 => '"B" must be equal to 1', + 2 => '"B" must be equal to 1', ] )); diff --git a/tests/feature/Issues/Issue1289Test.php b/tests/feature/Issues/Issue1289Test.php index 74722ef60..aa0babbdc 100644 --- a/tests/feature/Issues/Issue1289Test.php +++ b/tests/feature/Issues/Issue1289Test.php @@ -54,7 +54,7 @@ - description must be a string value FULL_MESSAGE, [ - 'allOf' => [ + 0 => [ '__root__' => 'These rules must pass for `["default": 2, "description": [], "children": ["nope"]]`', 'default' => [ '__root__' => 'Only one of these rules must pass for default', diff --git a/tests/feature/Issues/Issue1334Test.php b/tests/feature/Issues/Issue1334Test.php index 253115eb4..d61f2933a 100644 --- a/tests/feature/Issues/Issue1334Test.php +++ b/tests/feature/Issues/Issue1334Test.php @@ -37,13 +37,13 @@ function (): void { [ 'each' => [ '__root__' => 'Each item in `[["region": "Oregon", "country": "USA", "other": 123], ["street": "", "region": "Oregon", "country": "USA"], ["s ... ]` must be valid', - 'allOf.1' => [ + 0 => [ '__root__' => 'These rules must pass for `["region": "Oregon", "country": "USA", "other": 123]`', 'street' => 'street must be present', 'other' => 'other must be a string or must be null', ], - 'allOf.2' => 'street must not be empty', - 'allOf.3' => 'street must be a string', + 1 => 'street must not be empty', + 2 => 'street must be a string', ], ] )); diff --git a/tests/feature/Issues/Issue1348Test.php b/tests/feature/Issues/Issue1348Test.php index a44d28785..ced0cef7a 100644 --- a/tests/feature/Issues/Issue1348Test.php +++ b/tests/feature/Issues/Issue1348Test.php @@ -49,7 +49,7 @@ [ 'each' => [ '__root__' => 'Each item in `[["manufacturer": "Honda", "model": "Accord"], ["manufacturer": "Toyota", "model": "Rav4"], ["manufacturer": "Fo ... ]` must be valid', - 'oneOf.3' => [ + 2 => [ '__root__' => 'Only one of these rules must pass for `["manufacturer": "Ford", "model": "not real"]`', 'allOf.1' => [ '__root__' => 'All the required rules must pass for `["manufacturer": "Ford", "model": "not real"]`', @@ -63,7 +63,7 @@ ], 'allOf.3' => 'model must be in `["F150", "Bronco"]`', ], - 'oneOf.4' => [ + 3 => [ '__root__' => 'Only one of these rules must pass for `["manufacturer": "Honda", "model": "not valid"]`', 'allOf.1' => 'model must be in `["Accord", "Fit"]`', 'allOf.2' => [ diff --git a/tests/feature/Issues/Issue1469Test.php b/tests/feature/Issues/Issue1469Test.php index e9c3709da..b3756a809 100644 --- a/tests/feature/Issues/Issue1469Test.php +++ b/tests/feature/Issues/Issue1469Test.php @@ -41,8 +41,8 @@ function (): void { [ 'keySet' => [ '__root__' => 'Each item in order_items must be valid', - 'keySet.1' => 'quantity must be an integer value', - 'keySet.2' => [ + 0 => 'quantity must be an integer value', + 1 => [ '__root__' => 'order_items contains both missing and extra keys', 'product_title' => 'product_title must be present', 'quantity' => 'quantity must be present', diff --git a/tests/feature/Rules/EachTest.php b/tests/feature/Rules/EachTest.php index 4fbbd5edb..e63ec8b25 100644 --- a/tests/feature/Rules/EachTest.php +++ b/tests/feature/Rules/EachTest.php @@ -32,9 +32,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in `["a", "b", "c"]` must be valid', - 'intType.1' => '"a" must be an integer', - 'intType.2' => '"b" must be an integer', - 'intType.3' => '"c" must be an integer', + 0 => '"a" must be an integer', + 1 => '"b" must be an integer', + 2 => '"c" must be an integer', ] )); @@ -49,9 +49,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in `[1, 2, 3]` must be invalid', - 'intType.1' => '1 must not be an integer', - 'intType.2' => '2 must not be an integer', - 'intType.3' => '3 must not be an integer', + 0 => '1 must not be an integer', + 1 => '2 must not be an integer', + 2 => '3 must not be an integer', ] )); @@ -80,9 +80,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in Wrapped must be valid', - 'intType.1' => 'Wrapped must be an integer', - 'intType.2' => 'Wrapped must be an integer', - 'intType.3' => 'Wrapped must be an integer', + 0 => 'Wrapped must be an integer', + 1 => 'Wrapped must be an integer', + 2 => 'Wrapped must be an integer', ] )); @@ -97,9 +97,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in Wrapped must be invalid', - 'intType.1' => 'Wrapped must not be an integer', - 'intType.2' => 'Wrapped must not be an integer', - 'intType.3' => 'Wrapped must not be an integer', + 0 => 'Wrapped must not be an integer', + 1 => 'Wrapped must not be an integer', + 2 => 'Wrapped must not be an integer', ] )); @@ -114,9 +114,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in Wrapper must be valid', - 'intType.1' => 'Wrapper must be an integer', - 'intType.2' => 'Wrapper must be an integer', - 'intType.3' => 'Wrapper must be an integer', + 0 => 'Wrapper must be an integer', + 1 => 'Wrapper must be an integer', + 2 => 'Wrapper must be an integer', ] )); @@ -131,9 +131,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in Wrapper must be invalid', - 'intType.1' => 'Wrapper must not be an integer', - 'intType.2' => 'Wrapper must not be an integer', - 'intType.3' => 'Wrapper must not be an integer', + 0 => 'Wrapper must not be an integer', + 1 => 'Wrapper must not be an integer', + 2 => 'Wrapper must not be an integer', ] )); @@ -148,9 +148,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in Not must be invalid', - 'intType.1' => 'Not must not be an integer', - 'intType.2' => 'Not must not be an integer', - 'intType.3' => 'Not must not be an integer', + 0 => 'Not must not be an integer', + 1 => 'Not must not be an integer', + 2 => 'Not must not be an integer', ] )); @@ -192,9 +192,9 @@ ->setTemplates([ 'each' => [ '__root__' => 'Here a sequence of items that did not pass the validation', - 'intType.1' => 'First item should have been an integer', - 'intType.2' => 'Second item should have been an integer', - 'intType.3' => 'Third item should have been an integer', + 0 => 'First item should have been an integer', + 1 => 'Second item should have been an integer', + 2 => 'Third item should have been an integer', ], ]) ->assert(['a', 'b', 'c']), @@ -207,9 +207,9 @@ FULL_MESSAGE, [ '__root__' => 'Here a sequence of items that did not pass the validation', - 'intType.1' => 'First item should have been an integer', - 'intType.2' => 'Second item should have been an integer', - 'intType.3' => 'Third item should have been an integer', + 0 => 'First item should have been an integer', + 1 => 'Second item should have been an integer', + 2 => 'Third item should have been an integer', ] )); @@ -219,9 +219,9 @@ ->setTemplates([ 'Wrapped' => [ '__root__' => 'Here a sequence of items that did not pass the validation', - 'Wrapped.1' => 'First item should have been an integer', - 'Wrapped.2' => 'Second item should have been an integer', - 'Wrapped.3' => 'Third item should have been an integer', + 0 => 'First item should have been an integer', + 1 => 'Second item should have been an integer', + 2 => 'Third item should have been an integer', ], ]) ->assert(['a', 'b', 'c']), @@ -234,9 +234,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in Wrapped must be valid', - 'intType.1' => 'Wrapped must be an integer', - 'intType.2' => 'Wrapped must be an integer', - 'intType.3' => 'Wrapped must be an integer', + 0 => 'Wrapped must be an integer', + 1 => 'Wrapped must be an integer', + 2 => 'Wrapped must be an integer', ] )); @@ -254,12 +254,12 @@ FULL_MESSAGE, [ '__root__' => 'Each item in `[2, 4]` must be valid', - 'allOf.1' => [ + 0 => [ '__root__' => 'All the required rules must pass for 2', 'between' => '2 must be between 5 and 7', 'odd' => '2 must be an odd number', ], - 'allOf.2' => [ + 1 => [ '__root__' => 'All the required rules must pass for 4', 'between' => '4 must be between 5 and 7', 'odd' => '4 must be an odd number', @@ -282,9 +282,9 @@ FULL_MESSAGE, [ '__root__' => 'Each item in `[["not_int": "wrong"], ["my_int": 2], "not an array"]` must be valid', - 'allOf.1' => 'my_int must be present', - 'allOf.2' => 'my_int must be an odd number', - 'allOf.3' => [ + 0 => 'my_int must be present', + 1 => 'my_int must be an odd number', + 2 => [ '__root__' => 'All the required rules must pass for "not an array"', 'arrayType' => '"not an array" must be an array', 'my_int' => 'my_int must be present',