diff --git a/src/Failure/Failure.php b/src/Failure/Failure.php index 4ff0fa3..0455a8d 100644 --- a/src/Failure/Failure.php +++ b/src/Failure/Failure.php @@ -96,7 +96,7 @@ public function getMessage(): string * Returns the arguments passed to the rule specification. * * - * @return mixed[] + * @return array */ public function getArgs(): array { diff --git a/src/Failure/FailureCollection.php b/src/Failure/FailureCollection.php index e208b02..1e8cb20 100644 --- a/src/Failure/FailureCollection.php +++ b/src/Failure/FailureCollection.php @@ -107,7 +107,7 @@ protected function newFailure(string $field, string $message, array $args = arra * @param string $field The field name. * * - * @return mixed[] + * @return array */ public function forField(string $field): array { @@ -123,7 +123,7 @@ public function forField(string $field): array * Returns all failure messages for all fields. * * - * @return mixed[][] + * @return array> */ public function getMessages(): array { @@ -140,6 +140,8 @@ public function getMessages(): array * * @param string $field The field name. * + * @return array + * */ public function getMessagesForField(string $field): array { @@ -148,9 +150,15 @@ public function getMessagesForField(string $field): array } $messages = array(); - foreach ($this[$field] as $failure) { - $messages[] = $failure->getMessage(); + + if ($this[$field] instanceof FailureCollection) { + $messages = $this[$field]->getMessages(); + } else { + foreach ($this[$field] as $failure) { + $messages[] = $failure->getMessage(); + } } + return $messages; } @@ -193,4 +201,17 @@ public function getMessagesForFieldAsString(string $field, string $prefix = ''): } return $string; } + + public function addSubfieldFailures($field, $spec) + { + $failure_collection = new FailureCollection(); + + foreach ($spec->getMessage() as $f => $messages) { + foreach ($messages as $message) { + $failure_collection->add($f, $message, $spec->getArgs()); + } + } + + $this[$field] = $failure_collection; + } } diff --git a/src/Spec/Spec.php b/src/Spec/Spec.php index bfa6931..f286853 100644 --- a/src/Spec/Spec.php +++ b/src/Spec/Spec.php @@ -277,7 +277,7 @@ public function getField() * * Returns the failure message for this rule specification. * - * @return string + * @return string|array> * */ public function getMessage() diff --git a/src/Spec/SubSpec.php b/src/Spec/SubSpec.php index 28128d1..cd6838a 100644 --- a/src/Spec/SubSpec.php +++ b/src/Spec/SubSpec.php @@ -53,7 +53,8 @@ public function __construct(SubjectFilter $filter) public function __invoke($subject) { $field = $this->field; - $values =& $subject->$field; + $field_values = isset($subject->$field) ? $subject->$field : []; + $values =& $field_values; return $this->filter->apply($values); } diff --git a/src/SubjectFilter.php b/src/SubjectFilter.php index 9a100a5..3f51963 100644 --- a/src/SubjectFilter.php +++ b/src/SubjectFilter.php @@ -220,7 +220,7 @@ public function sanitize(string $field): Spec * * */ - public function subfilter(string $field, $class = \Aura\Filter\SubjectFilter::class): Spec + public function subFilter(string $field, $class = \Aura\Filter\SubjectFilter::class): Spec { $spec = $this->sub_spec_factory->newSubSpec($class); return $this->addSpec($spec, $field); @@ -363,9 +363,9 @@ protected function applySpec(Spec $spec, object $subject): bool * * @param Spec $spec The failed rule specification. * - * + * @return void */ - protected function failed(Spec $spec): Failure + protected function failed(Spec $spec) { $field = $spec->getField(); @@ -373,11 +373,19 @@ protected function failed(Spec $spec): Failure $this->skip[$field] = true; } + if ($spec instanceof SubSpec) { + $this->failures->addSubfieldFailures($field, $spec); + + return; + } + if (isset($this->field_messages[$field])) { - return $this->failures->set($field, $this->field_messages[$field]); + $this->failures->set($field, $this->field_messages[$field]); + + return; } - return $this->failures->add($field, $spec->getMessage(), $spec->getArgs()); + $this->failures->add($field, $spec->getMessage(), $spec->getArgs()); } /** diff --git a/tests/Spec/SubspecTest.php b/tests/Spec/SubspecTest.php new file mode 100644 index 0000000..991728e --- /dev/null +++ b/tests/Spec/SubspecTest.php @@ -0,0 +1,65 @@ +filter = $filter_factory->newSubjectFilter(); + } + + public function testMultidimensionalSupport() + { + $data = [ + 'id' => 'asd', + 'user' => [ + 'name' => 'Foo', + 'age' => 'asd', + ], + // 'url' => 'http://example.com' + ]; + + $this->filter->validate('id')->is('int'); + $this->filter->validate('url')->is('url'); + + $user_spec = $this->filter->subFilter('user'); // add a "SubSpec" + $user_filter = $user_spec->filter(); // Get the "SubSpec" SubjectFilter + + $user_filter->validate('given-name')->isNotBlank(); + $user_filter->validate('age')->is('int'); + $user_filter->validate('gender')->is('strlen', 1); + + $subject = (object) $data; + $result = $this->filter->apply($subject); + $this->assertFalse($result); + $expect = [ + 'id' => [ + 'id should have validated as int' + ], + 'url' => [ + 'url should have validated as url', + ], + 'user' => [ + 'given-name' => [ + 'given-name should not have been blank', + ], + 'age' => [ + 'age should have validated as int' + ], + 'gender' => [ + 'gender should have validated as strlen(1)' + ] + ] + ]; + $actual = $this->filter->getFailures()->getMessages(); + $this->assertSame($expect, $actual); + } +}