Skip to content

Commit

Permalink
Fix generating property schema with Unique restriction
Browse files Browse the repository at this point in the history
  • Loading branch information
norkunas authored and soyuka committed Mar 25, 2021
1 parent 9c348d2 commit f74649b
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -16,6 +16,7 @@

## 2.6.4

* JSON Schema: Fix generating property schema with Unique restriction (#4159)
* Serializer: Fix denormalization of basic property-types in XML and CSV (#3191)
* Serializer: Fix denormalization of collection with one element in XML (#4154)
* JSON Schema: Manage Sequentially and AtLeastOneOf constraints when generating property metadata (#4139 and #4147)
Expand Down
4 changes: 4 additions & 0 deletions src/Bridge/Symfony/Bundle/Resources/config/validator.xml
Expand Up @@ -34,6 +34,10 @@
<tag name="api_platform.metadata.property_schema_restriction"/>
</service>

<service id="api_platform.metadata.property_schema.unique_restriction" class="ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaUniqueRestriction" public="false">
<tag name="api_platform.metadata.property_schema_restriction"/>
</service>

<service id="api_platform.listener.view.validate" class="ApiPlatform\Core\Validator\EventListener\ValidateListener">
<argument type="service" id="api_platform.validator" />
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
Expand Down
@@ -0,0 +1,40 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction;

use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Unique;

/**
* @author Tomas Norkūnas <norkunas.tom@gmail.com>
*/
final class PropertySchemaUniqueRestriction implements PropertySchemaRestrictionMetadataInterface
{
/**
* {@inheritdoc}
*/
public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array
{
return ['uniqueItems' => true];
}

/**
* {@inheritdoc}
*/
public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool
{
return $constraint instanceof Unique;
}
}
Expand Up @@ -1339,6 +1339,7 @@ private function getBaseContainerBuilderProphecyWithoutDefaultMetadataLoading(ar
'api_platform.metadata.property_schema.one_of_restriction',
'api_platform.metadata.property_schema.regex_restriction',
'api_platform.metadata.property_schema.format_restriction',
'api_platform.metadata.property_schema.unique_restriction',
'api_platform.metadata.property.metadata_factory.yaml',
'api_platform.metadata.property.name_collection_factory.yaml',
'api_platform.metadata.resource.filter_metadata_factory.annotation',
Expand Down
@@ -0,0 +1,57 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Tests\Bridge\Symfony\Validator\Metadata\Property\Restriction;

use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaUniqueRestriction;
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
use ApiPlatform\Core\Tests\ProphecyTrait;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Positive;
use Symfony\Component\Validator\Constraints\Unique;

/**
* @author Tomas Norkūnas <norkunas.tom@gmail.com>
*/
final class PropertySchemaUniqueRestrictionTest extends TestCase
{
use ProphecyTrait;

private $propertySchemaUniqueRestriction;

protected function setUp(): void
{
$this->propertySchemaUniqueRestriction = new PropertySchemaUniqueRestriction();
}

/**
* @dataProvider supportsProvider
*/
public function testSupports(Constraint $constraint, PropertyMetadata $propertyMetadata, bool $expectedResult): void
{
self::assertSame($expectedResult, $this->propertySchemaUniqueRestriction->supports($constraint, $propertyMetadata));
}

public function supportsProvider(): \Generator
{
yield 'supported' => [new Unique(), new PropertyMetadata(), true];

yield 'not supported' => [new Positive(), new PropertyMetadata(), false];
}

public function testCreate(): void
{
self::assertSame(['uniqueItems' => true], $this->propertySchemaUniqueRestriction->create(new Unique(), new PropertyMetadata()));
}
}
Expand Up @@ -17,12 +17,14 @@
use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction;
use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaOneOfRestriction;
use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction;
use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaUniqueRestriction;
use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\ValidatorPropertyMetadataFactory;
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
use ApiPlatform\Core\Tests\Fixtures\DummyAtLeastOneOfValidatedEntity;
use ApiPlatform\Core\Tests\Fixtures\DummyIriWithValidationEntity;
use ApiPlatform\Core\Tests\Fixtures\DummySequentiallyValidatedEntity;
use ApiPlatform\Core\Tests\Fixtures\DummyUniqueValidatedEntity;
use ApiPlatform\Core\Tests\Fixtures\DummyValidatedEntity;
use ApiPlatform\Core\Tests\ProphecyTrait;
use Doctrine\Common\Annotations\AnnotationReader;
Expand Down Expand Up @@ -406,4 +408,30 @@ public function testCreateWithAtLeastOneOfConstraint(): void
['minLength' => 10],
], $schema['oneOf']);
}

public function testCreateWithPropertyUniqueRestriction(): void
{
$validatorClassMetadata = new ClassMetadata(DummyUniqueValidatedEntity::class);
(new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata);

$validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class);
$validatorMetadataFactory->getMetadataFor(DummyUniqueValidatedEntity::class)
->willReturn($validatorClassMetadata)
->shouldBeCalled();

$decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
$decoratedPropertyMetadataFactory->create(DummyUniqueValidatedEntity::class, 'dummyItems', [])->willReturn(
new PropertyMetadata()
)->shouldBeCalled();

$validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory(
$validatorMetadataFactory->reveal(),
$decoratedPropertyMetadataFactory->reveal(),
[new PropertySchemaUniqueRestriction()]
);

$schema = $validationPropertyMetadataFactory->create(DummyUniqueValidatedEntity::class, 'dummyItems')->getSchema();

$this->assertSame(['uniqueItems' => true], $schema);
}
}
26 changes: 26 additions & 0 deletions tests/Fixtures/DummyUniqueValidatedEntity.php
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Tests\Fixtures;

use Symfony\Component\Validator\Constraints as Assert;

class DummyUniqueValidatedEntity
{
/**
* @var string[]
*
* @Assert\Unique
*/
public $dummyItems;
}

0 comments on commit f74649b

Please sign in to comment.