mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-03-11 18:16:13 +03:00
Compound validation rule support (#1818)
* Compound validation rule support * Compound validation rule support * Compound validation rule support * Compound validation rule support * Remove duplicated method * error during merge * wrong variable name * Simplify PR * Fix CS * Use same indentation as before Co-authored-by: Guilhem Niot <guilhem@gniot.fr> Co-authored-by: Guilhem Niot <guilhem.niot@gmail.com>
This commit is contained in:
parent
187f55941c
commit
2df454c0c3
@ -44,22 +44,33 @@ class SymfonyConstraintAnnotationReader
|
||||
*/
|
||||
public function updateProperty($reflection, OA\Property $property): void
|
||||
{
|
||||
foreach ($this->getAnnotations($reflection) as $annotation) {
|
||||
foreach ($this->getAnnotations($reflection) as $outerAnnotation) {
|
||||
$innerAnnotations = $outerAnnotation instanceof Assert\Compound
|
||||
? $outerAnnotation->constraints
|
||||
: [$outerAnnotation];
|
||||
|
||||
$this->processPropertyAnnotations($reflection, $property, $innerAnnotations);
|
||||
}
|
||||
}
|
||||
|
||||
private function processPropertyAnnotations($reflection, OA\Property $property, $annotations)
|
||||
{
|
||||
foreach ($annotations as $annotation) {
|
||||
if ($annotation instanceof Assert\NotBlank || $annotation instanceof Assert\NotNull) {
|
||||
// To support symfony/validator < 4.3
|
||||
if ($annotation instanceof Assert\NotBlank && \property_exists($annotation, 'allowNull') && $annotation->allowNull) {
|
||||
// The field is optional
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// The field is required
|
||||
if (null === $this->schema) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
$propertyName = $this->getSchemaPropertyName($property);
|
||||
if (null === $propertyName) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
$existingRequiredFields = OA\UNDEFINED !== $this->schema->required ? $this->schema->required : [];
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\Functional\Entity;
|
||||
|
||||
use Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture as CustomAssert;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
class SymfonyConstraints
|
||||
@ -109,6 +110,18 @@ class SymfonyConstraints
|
||||
*/
|
||||
private $propertyLessThanOrEqual;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @CustomAssert\CompoundValidationRule()
|
||||
*/
|
||||
private $propertyWithCompoundValidationRule;
|
||||
|
||||
public function setPropertyWithCompoundValidationRule(int $propertyWithCompoundValidationRule): void
|
||||
{
|
||||
$this->propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Assert\Count(min="0", max="10")
|
||||
*/
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Nelmio\ApiDocBundle\Tests\Functional;
|
||||
|
||||
use Nelmio\ApiDocBundle\OpenApiPhp\Util;
|
||||
use Nelmio\ApiDocBundle\Tests\Helper;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Symfony\Component\Serializer\Annotation\SerializedName;
|
||||
|
||||
@ -355,7 +356,7 @@ class FunctionalTest extends WebTestCase
|
||||
|
||||
public function testSymfonyConstraintDocumentation()
|
||||
{
|
||||
$this->assertEquals([
|
||||
$expected = [
|
||||
'required' => [
|
||||
'propertyNotBlank',
|
||||
'propertyNotNull',
|
||||
@ -419,10 +420,26 @@ class FunctionalTest extends WebTestCase
|
||||
'type' => 'integer',
|
||||
'maximum' => 23,
|
||||
],
|
||||
'propertyWithCompoundValidationRule' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
],
|
||||
'type' => 'object',
|
||||
'schema' => 'SymfonyConstraints',
|
||||
], json_decode($this->getModel('SymfonyConstraints')->toJson(), true));
|
||||
];
|
||||
|
||||
if (Helper::isCompoundValidatorConstraintSupported()) {
|
||||
$expected['required'][] = 'propertyWithCompoundValidationRule';
|
||||
$expected['properties']['propertyWithCompoundValidationRule'] = [
|
||||
'type' => 'integer',
|
||||
'maximum' => 5,
|
||||
'exclusiveMaximum' => true,
|
||||
'minimum' => 0,
|
||||
'exclusiveMinimum' => true,
|
||||
];
|
||||
}
|
||||
|
||||
$this->assertEquals($expected, json_decode($this->getModel('SymfonyConstraints')->toJson(), true));
|
||||
}
|
||||
|
||||
public function testConfigReference()
|
||||
|
17
Tests/Helper.php
Normal file
17
Tests/Helper.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests;
|
||||
|
||||
use PackageVersions\Versions;
|
||||
|
||||
final class Helper
|
||||
{
|
||||
public static function isCompoundValidatorConstraintSupported(): bool
|
||||
{
|
||||
$validatorVersion = Versions::getVersion('symfony/validator');
|
||||
|
||||
return version_compare($validatorVersion, 'v5.1', '>=');
|
||||
}
|
||||
}
|
10
Tests/ModelDescriber/Annotations/Fixture/CompoundStub.php
Normal file
10
Tests/ModelDescriber/Annotations/Fixture/CompoundStub.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture;
|
||||
|
||||
class CompoundStub
|
||||
{
|
||||
public $constraints = [];
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture;
|
||||
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Constraints\Compound;
|
||||
|
||||
if (!class_exists(Compound::class)) {
|
||||
class_alias(CompoundStub::class, Compound::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
*/
|
||||
final class CompoundValidationRule extends Compound
|
||||
{
|
||||
protected function getConstraints(array $options): array
|
||||
{
|
||||
return [
|
||||
new Assert\Type('numeric'),
|
||||
new Assert\NotBlank(),
|
||||
new Assert\Positive(),
|
||||
new Assert\LessThan(5),
|
||||
];
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@ namespace Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations;
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Nelmio\ApiDocBundle\ModelDescriber\Annotations\SymfonyConstraintAnnotationReader;
|
||||
use Nelmio\ApiDocBundle\Tests\Helper;
|
||||
use Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture as CustomAssert;
|
||||
use OpenApi\Annotations as OA;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
@ -245,6 +247,39 @@ class SymfonyConstraintAnnotationReaderTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testCompoundValidationRules()
|
||||
{
|
||||
$entity = new class() {
|
||||
/**
|
||||
* @CustomAssert\CompoundValidationRule()
|
||||
*/
|
||||
private $property1;
|
||||
};
|
||||
$propertyName = 'property1';
|
||||
|
||||
$schema = new OA\Schema([]);
|
||||
$schema->merge([new OA\Property(['property' => $propertyName])]);
|
||||
|
||||
$symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader());
|
||||
$symfonyConstraintAnnotationReader->setSchema($schema);
|
||||
|
||||
$symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, $propertyName), $schema->properties[0]);
|
||||
|
||||
if (Helper::isCompoundValidatorConstraintSupported()) {
|
||||
$this->assertSame([$propertyName], $schema->required);
|
||||
$this->assertSame(0, $schema->properties[0]->minimum);
|
||||
$this->assertTrue($schema->properties[0]->exclusiveMinimum);
|
||||
$this->assertSame(5, $schema->properties[0]->maximum);
|
||||
$this->assertTrue($schema->properties[0]->exclusiveMaximum);
|
||||
} else {
|
||||
$this->assertSame(OA\UNDEFINED, $schema->required);
|
||||
$this->assertSame(OA\UNDEFINED, $schema->properties[0]->minimum);
|
||||
$this->assertSame(OA\UNDEFINED, $schema->properties[0]->exclusiveMinimum);
|
||||
$this->assertSame(OA\UNDEFINED, $schema->properties[0]->maximum);
|
||||
$this->assertSame(OA\UNDEFINED, $schema->properties[0]->exclusiveMaximum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $entity
|
||||
* @group https://github.com/nelmio/NelmioApiDocBundle/issues/1821
|
||||
|
@ -52,7 +52,8 @@
|
||||
"friendsofsymfony/rest-bundle": "^2.8|^3.0",
|
||||
"willdurand/hateoas-bundle": "^1.0|^2.0",
|
||||
"jms/serializer-bundle": "^2.3|^3.0",
|
||||
"jms/serializer": "^1.14|^3.0"
|
||||
"jms/serializer": "^1.14|^3.0",
|
||||
"composer/package-versions-deprecated": "1.11.99.1"
|
||||
},
|
||||
"suggest": {
|
||||
"api-platform/core": "For using an API oriented framework.",
|
||||
|
Loading…
x
Reference in New Issue
Block a user