Skip to content

Commit

Permalink
Added StructValidator to ease usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Steveb-p committed Nov 18, 2024
1 parent 733af52 commit d377571
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/bundle/Core/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 34 additions & 0 deletions src/contracts/Validation/StructValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Validation;

use Symfony\Component\Validator\Validator\ValidatorInterface;

final class StructValidator
{
private ValidatorInterface $validator;

public function __construct(ValidatorInterface $validator)
{
$this->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);
}
}
}
94 changes: 94 additions & 0 deletions tests/lib/Validation/StructValidatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Core\Validation;

use Ibexa\Contracts\Core\Validation\StructValidator;
use Ibexa\Contracts\Core\Validation\ValidationFailedException;
use PHPUnit\Framework\TestCase;
use stdClass;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
* @covers \Ibexa\Contracts\Core\Validation\StructValidator
*/
final class StructValidatorTest extends TestCase
{
/** @var \Symfony\Component\Validator\Validator\ValidatorInterface&\PHPUnit\Framework\MockObject\MockObject) */
private ValidatorInterface $validator;

private StructValidator $structValidator;

protected function setUp(): void
{
$this->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]);
}
}

0 comments on commit d377571

Please sign in to comment.