diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index c9a78fe8cd06..86fbfc8769eb 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -314,22 +314,29 @@ protected function replacePlaceholders($data) $originalData = []; foreach ($data as $key => $value) { - if (is_array($value)) { - $value = $this->replacePlaceholders($value); - } - - $key = str_replace( - [$this->dotPlaceholder, '__asterisk__'], - ['.', '*'], - $key - ); - - $originalData[$key] = $value; + $originalData[$this->replacePlaceholderInString($key)] = is_array($value) + ? $this->replacePlaceholders($value) + : $value; } return $originalData; } + /** + * Replace the placeholders in the given string. + * + * @param string $value + * @return string + */ + protected function replacePlaceholderInString(string $value) + { + return str_replace( + [$this->dotPlaceholder, '__asterisk__'], + ['.', '*'], + $value + ); + } + /** * Add an after validation callback. * @@ -722,6 +729,10 @@ protected function hasNotFailedPreviousRuleIfPresenceRule($rule, $attribute) */ protected function validateUsingCustomRule($attribute, $value, $rule) { + $attribute = $this->replacePlaceholderInString($attribute); + + $value = is_array($value) ? $this->replacePlaceholders($value) : $value; + if (! $rule->passes($attribute, $value)) { $this->failedRules[$attribute][get_class($rule)] = []; @@ -745,12 +756,14 @@ protected function validateUsingCustomRule($attribute, $value, $rule) */ protected function shouldStopValidating($attribute) { + $cleanedAttribute = $this->replacePlaceholderInString($attribute); + if ($this->hasRule($attribute, ['Bail'])) { - return $this->messages->has($attribute); + return $this->messages->has($cleanedAttribute); } - if (isset($this->failedRules[$attribute]) && - array_key_exists('uploaded', $this->failedRules[$attribute])) { + if (isset($this->failedRules[$cleanedAttribute]) && + array_key_exists('uploaded', $this->failedRules[$cleanedAttribute])) { return true; } @@ -758,8 +771,8 @@ protected function shouldStopValidating($attribute) // and that rule already failed then we should stop validation at this point // as now there is no point in calling other rules with this field empty. return $this->hasRule($attribute, $this->implicitRules) && - isset($this->failedRules[$attribute]) && - array_intersect(array_keys($this->failedRules[$attribute]), $this->implicitRules); + isset($this->failedRules[$cleanedAttribute]) && + array_intersect(array_keys($this->failedRules[$cleanedAttribute]), $this->implicitRules); } /** diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index c65fc2fefc93..826aeef296c3 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -4932,6 +4932,51 @@ public function message() $this->assertSame('validation.string', $v->errors()->get('name')[2]); } + public function testCustomValidationObjectWithDotKeysIsCorrectlyPassedValue() + { + $v = new Validator( + $this->getIlluminateArrayTranslator(), + ['foo' => ['foo.bar' => 'baz']], + [ + 'foo' => new class implements Rule { + public function passes($attribute, $value) + { + return $value === ['foo.bar' => 'baz']; + } + + public function message() + { + return ':attribute must be baz'; + } + }, + ] + ); + + $this->assertTrue($v->passes()); + + // Test failed attributes contains proper entries + $v = new Validator( + $this->getIlluminateArrayTranslator(), + ['foo' => ['foo.bar' => 'baz']], + [ + 'foo.foo\.bar' => new class implements Rule { + public function passes($attribute, $value) + { + return false; + } + + public function message() + { + return ':attribute must be baz'; + } + }, + ] + ); + + $this->assertFalse($v->passes()); + $this->assertTrue(is_array($v->failed()['foo.foo.bar'])); + } + public function testImplicitCustomValidationObjects() { // Test passing case...