From d377571bd86256c890cd126f659d9e5db40d499f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Mon, 18 Nov 2024 09:55:57 +0100 Subject: [PATCH] Added StructValidator to ease usage --- src/bundle/Core/Resources/config/services.yml | 2 + src/contracts/Validation/StructValidator.php | 34 +++++++ tests/lib/Validation/StructValidatorTest.php | 94 +++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/contracts/Validation/StructValidator.php create mode 100644 tests/lib/Validation/StructValidatorTest.php diff --git a/src/bundle/Core/Resources/config/services.yml b/src/bundle/Core/Resources/config/services.yml index 2988c4b2cf..0cc9d003e4 100644 --- a/src/bundle/Core/Resources/config/services.yml +++ b/src/bundle/Core/Resources/config/services.yml @@ -371,6 +371,8 @@ services: Ibexa\Bundle\Core\Translation\Policy\PolicyTranslationDefinitionProvider: ~ + Ibexa\Contracts\Core\Validation\StructValidator: ~ + Ibexa\Contracts\Core\Validation\StructWrapperValidator: decorates: 'validator' # Decorator priority is higher than debug.validator to ensure profiler receives struct errors diff --git a/src/contracts/Validation/StructValidator.php b/src/contracts/Validation/StructValidator.php new file mode 100644 index 0000000000..b0073afbf4 --- /dev/null +++ b/src/contracts/Validation/StructValidator.php @@ -0,0 +1,34 @@ +validator = $validator; + } + + /** + * @throws \Ibexa\Contracts\Core\Validation\ValidationFailedException + * + * @param string[] $groups + */ + public function assertValidStruct(string $name, object $struct, array $groups): void + { + $errors = $this->validator->validate($struct, null, ['Default', ...$groups]); + if ($errors->count() > 0) { + throw new ValidationFailedException($name, $errors); + } + } +} diff --git a/tests/lib/Validation/StructValidatorTest.php b/tests/lib/Validation/StructValidatorTest.php new file mode 100644 index 0000000000..8a81ab5e6f --- /dev/null +++ b/tests/lib/Validation/StructValidatorTest.php @@ -0,0 +1,94 @@ +validator = $this->createMock(ValidatorInterface::class); + $this->structValidator = new StructValidator($this->validator); + } + + public function testAssertValidStructWithValidStruct(): void + { + $struct = new stdClass(); + $errors = $this->createMock(ConstraintViolationListInterface::class); + $errors->method('count')->willReturn(0); + + $this->validator + ->expects(self::once()) + ->method('validate') + ->with( + $struct, + null, + ['Default', 'group'] + )->willReturn($errors); + + $this->structValidator->assertValidStruct('struct', new stdClass(), ['group']); + } + + public function testAssertValidStructWithInvalidStruct(): void + { + $errors = $this->createExampleConstraintViolationList( + $this->createExampleConstraintViolation() + ); + + $this->validator + ->method('validate') + ->with( + new stdClass(), + null, + ['Default', 'group'] + )->willReturn($errors); + + try { + $this->structValidator->assertValidStruct('struct', new stdClass(), ['group']); + } catch (ValidationFailedException $e) { + self::assertSame("Argument 'struct->property' is invalid: validation error", $e->getMessage()); + self::assertSame($errors, $e->getErrors()); + } + } + + private function createExampleConstraintViolation(): ConstraintViolationInterface + { + return new ConstraintViolation( + 'validation error', + null, + [], + '', + 'property', + 'example' + ); + } + + private function createExampleConstraintViolationList( + ConstraintViolationInterface $error + ): ConstraintViolationListInterface { + return new ConstraintViolationList([$error]); + } +}